MS Scripting

PoshCode OpenSearch

Huddled Masses - Thu, 2008-09-11 22:17

Well, an interesting comment came up today that the new version of PoshCode.org that we’re working on should support OpenSearch and of course, me being me, I said: oh, OpenSearch is easy, gimme a minute…

And three hours later, I’m going to bed.

However, I did manage to add paging support so you can “browse” the repository, and of course … to add OpenSearch. If you visit the repository with an OpenSearch aware browser, like say … Firefox 3, or IE 7, you’ll get a little glowing notification on your search bar that there is a search engine available. You can quickly add PoshCode’s search to your browser with a couple of clicks, and in no time flat you’re searching for PowerShell script.

Incidentally, I also hooked the OpenSearch stuff up to our API output, so OpenSearch aware apps which do not simply render the HTML page can get RSS output that should work for you. We’re not doing all of OpenSearch at this point, but I think the important bits are there (certainly the bits supported in your web browser are).

Feedback is welcome as always, let us know what you think of the new stuff by emailing feedback at poshcode …

Categories: MS Scripting, powershell

Euler #2

jaredpar's WebLog - Thu, 2008-09-11 05:01

Problem #2 came quite a bit faster. The yield syntax in F# is very similar to the C# iterator syntax and made translating this sample a breeze. 

As a commenter posted, in problem #1, I would've been better served to use Seq.filter as opposed to Seq.choose for the purpose of filtering list.  I've applied that here.  One downfall of learning a new language is finding the right API.  I spent a bit of time reading through the Seq documentation looking for the equivalent of the Where extension method and could only find chose.  Lesson learned

// Find the sum of all the even-valued terms in the sequence which do not exceed four million.
let problem2() =
    let rec fib prev cur = seq {
            yield prev
            if cur < 4000000 then
                yield! fib cur (prev+cur)
        }
    fib 1 2
        |> Seq.filter (fun x -> 0 = x % 2)
        |> Seq.sum

Categories: MS Scripting

PInvoke Interop Assistant on Channel 9

jaredpar's WebLog - Thu, 2008-09-11 05:00

Beth Massi dropped by my office a couple of months ago and we did a channel 9 video on the PInvoke Interop Assistant.  Mainly an overview of the product and a bit of a tutorial.  Check out the video here.

http://channel9.msdn.com/posts/funkyonex/The-P-Invoke-Interop-Assistant/

Categories: MS Scripting

Debugging F# list's

jaredpar's WebLog - Wed, 2008-09-10 05:00

One of the lacking's of the latest F# CTP is debugger visualization support for the built-in list types.  Viewing a list in the debugger is decidedly tedious compared to the mscorlib collection classes.  Take the following quick code sample

module Main = do let l1 = [0..4] let l2 = List.map (fun a -> a.ToString()) l1 let l3 = new System.Collections.Generic.List<int>() List.iter (fun i -> l3.Add(i)) l1 MainModuleTemp.Main() // Breakpoint here

Hit F5 in a F# console application and you'll get the following display.

image

Notice how the elements of the mscorlib List<> are immediately visible.  Getting to the data in a F# list is possible but it takes a lot more clicks than the mscorlib version.  This doesn't appear to be an oversight on the F# team either.  The expansion of mscorlib List<T> is controlled by the DebuggerTypeProxy attribute on the class definition.  If you fire up Reflector and dig into Fsharp.Core.dll and navigate to List<T> you'll notice it indeed has a DebuggerTypeProxy entry which is well formed and points to ListDebugView<T>. 

ListDebugView<T> is essentially identical to the one for mscorlib List<T>.  So what gives?  The bug appears to be in the accessibility of the constructor.  Even though it's not explicit in the documentation of DebuggerTypeProxy, it appears that the target type must have a single argument constructor which is public.  The one for ListDebugView<T> is internal. 

Normally this would be an easy enough problem to work around.  Add an assembly level attribute of type DebuggerTypeProxy pointing to List<T> and a modified version of ListDebugView.  Unfortunately that will not work in this case.  The debugger will prefer DebuggerTypeProxy instances added directly to a type over ones defined at an assembly level. 

That is, except for two cases.  The debugger will give precedence to assembly level attributes which are defined in an assembly named autoexp.dll and placed in one of the following two locations

  1. Visualizers folder for the current user.  One my machine it is C:\Users\jaredp\Documents\Visual Studio 2008\Visualizers
  2. Devenv global visualizer folder. C:\Program Files\Microsoft Visual Studio 9.0\Common7\Packages\Debugger\Visualizers\Original

If you navigate to either of these directories you will find both the default autoexp.dll and the source code used to compile it.  It's got quite a few entries you may want to add in a modified version.  Adding a new ListDebugView<T> here is possible but lets do it in F# instead.

Since autoexp.dll has predecence all we need to do is build a new version which has the appropriate debugger attributes for the F# collections.  Fire up a new class library project named autoexp and have it output to either of the directories listed above.  Below is a sample definition to get you started.

#light open System.Diagnostics module Main = type ListProxy<'a>(l:List<'a>) = [<DebuggerBrowsableAttribute(DebuggerBrowsableState.RootHidden)>] member this.Items = Array.of_list l [<assembly: DebuggerDisplayAttribute("{Length}", Target=typeof<List<int>>)>] [<assembly: DebuggerTypeProxyAttribute(typeof<ListProxy<int>>, Target=typeof<List<int>>)>] do ()

Don't be alarmed at the typeof<List<int>>.  The visualizer will work for any generic binding of List<T>.  In fact, reflector confirms that this attribute will be emitted with the type pointing at the unbound List<T> instead of List<int>. My lack of F# skills is failing me as to why.  I'd love to cry bug but I've found crying bug at a compiler is usually ... wrong. 

In either case, once you build this and place in the appropriate folder, you should find the visualizations for List<> much more accessible.

image

Categories: MS Scripting

When to use Type Inference

jaredpar's WebLog - Tue, 2008-09-09 05:00

Occasionally the debate will come as to when it's OK to use type inference in order to declare a variable.  There appear to be three groups in this debate.

  1. Whenever it's possible
  2. Only when it's absolutely clear what the type is
  3. Never, type inference is evil

I fall into camp #1 and here are my reasons

  • It does not reduce type safety.  This doesn't allow for any late binding, type unsafe functions or the like.  It simply lets the compiler chose the type for you.
  • It will actually increase type safety in your code.  The best example of this is the foreach statement on non-generic IEnumerable instances.  These foreach statements are all technically unsafe because the compiler must do a cast of the Current member under the hood.  This declaration looks no different than the type safe generic version of IEnumerable.  Using var will force you to write an explicit cast.  

foreach (SomeType cur in col)

foreach ( var cur in col.Cast<SomeType>())

  • Maintains the principles of DRY.  This is mostly true for cases where you have an explicit constructor on the RHS.
  • For some types, this is a requirement in order to use the type (anonymous types for instance).  I'm a big fan of consistency and since I must have some instances use type inference, I'd like to use them everywhere. 
  • Makes refactoring easier.  I re-factor, a lot.  I constantly split up or rename types.  Often in such a way that refactoring tools don't fixup all of the problems.  With var declarations I don't have to worry because they just properly infer their new type and happily chug along.  For explicit type cases I have to manually update all of the type names. 
  • Less typing with no loss of functionality.

The best argument I've heard against type inference is that it reduces readability since you can't look at a variable and know it's type.  True, but just hover over the declaration and the IDE will display the type.  Yes this is not possible with a non-IDE editor but how often do you use one?

Categories: MS Scripting

Virtualization launch day

John Howard - Mon, 2008-09-08 13:30

Today is (was) Virtualization Launch day. Although the keynote presentations were streamed live (in fact I'm just watching Bob Muglia finish up as I'm typing this), they will be available later this afternoon for on-demand viewing here.

Some of the highlights:

  • Microsoft Hyper-V Server is coming within the next 30 days and will be free
  • System Center Virtual Machine Manager 2008 (SCVMM) is coming within the next 30 days.
  • Live migration will be in the next release of Hyper-V in Windows Server 2008 codename "R2"


Microsoft Hyper-V Server
There's more information on Microsoft Hyper-V Server here as first announced back at TechEd last year. It will be available for free. Microsoft Hyper-V Server contains the same fundamental technology present in the Hyper-V role in Windows Server 2008, but Hyper-V is the only capability of Microsoft Hyper-V Server. It must be managed remotely. You may have noticed if you've watched the streaming media, the screenshot showed a command-line configuration utility - this is a simple way of configuring the server for things such as IP configuration, computer name, enabling remote desktop etc. More on that to follow soon.

System Center Virtual Machine Manager 2008
There's more information on SCVMM here. The main announcement today was that SCVMM 2008 will be available within 30 days. The demonstration showed SCVMM managing Virtual Server 2005 R2 SP1; Windows Server 2008 with Hyper-V; Microsoft Hyper-V Server and VMWare ESX 3.5.

Live Migration
This was the first time we've made any announcements about the feature set in Windows Server 2008 codename "R2". Live migration is the ability to move a running virtual machine from one physical server to another with little or no perceptible downtime from an end user perspective - today's keynote showed a video being played while the virtual machine on which Windows Media Player was running was "live-migrated". Although there are many more improvements in the next release that we've been working on for many months now, there will be a fuller disclosure at the PDC conference at the end of October this year, and also at WinHEC in November.

Cheers,
John.

Euler and F#

jaredpar's WebLog - Mon, 2008-09-08 05:00

I've been looking for some new problems to work on in F# to get more comfortable with the language.  I've been rather slack of late because of other projects but I had a little bit of time this week.  I decided it would be fun to join the crowd and play away at the problems on the project euler site.  That being said, answer #1.

module Euler = let problem1() = let test i = match (0 = i % 3) || (0 = i % 5) with | true -> Some i | false -> None let targetSeq = Seq.choose test [0..999] Seq.sum targetSeq
Categories: MS Scripting

Cisco is now a qualified IP PBX for Direct SIP with OCS 2007

MS Goodies - Sat, 2008-09-06 13:45

The following versions of Cisco Unified Communications Manager has been qualified for Direct SIP integration with Microsoft Office Communications Server 2007 (It has been working with some restrictions for quite a while, but is now a tested and “qualified” solution)-

4.2[3]sr3a, 5.1.3.3000-5 & 5.1.3.1000-12 and not least 6.1.1.3000-2

Note that interoperability requires the August 2008 Update Package for OCS 2007 as described in KB952780 and also KB952783 although the latter it is not listed on the UC OIP page. KB957280 is for the Mediation Server role and KB952783 are for all the other roles (Automatically delivered through Microsoft Update). Also the Office Communicator 2007 client update KB954439 is required according to KB957285 (This upgrade currently has to be requested directly through PSS).

The fixes (that we have been waiting for quite a while) allows you to select to break some of OCS 2007 RFC 3966 compliant use of E.164 numbers for interoperability with “certain” PBXs (Read Cisco but it may also apply to other vendors) that do not correctly use or understand the + sign in a E.164 number.

Following are the changes as explained in KB92785 “Outgoing calls from Communications Server 2007 Mediation Server may not be routed correctly” -

By default, Microsoft Office Communications Server 2007 Mediation Server uses a plus sign (+) to prefix E.164 numbers in the Request Uniform Resource Identifier (URI) for outgoing calls. However, certain private branch exchanges (PBXs) do not accept numbers that are prefixed by using a plus sign (+). Therefore, an outgoing call may not be routed correctly. Additionally, the "From" headers for incoming calls from certain PBXs do not comply with Requests for Comments (RFC) 3966, "The tel URI for Telephone Numbers." In this case, Office Communicator does not resolve the number to the correct user.

To make sure that Mediation Server operates correctly together with PBXs, update 952780 adds a new Mediation Server configuration file setting for Communications Server 2007. This configuration file is called RemovePlusFromRequestURI, and it contains one of two settings, YES or NO. If your PBX does not accept numbers that are prefixed by using a plus sign (+), the setting in the configuration file should be YES. The YES setting causes Mediation Server to remove the plus sign (+) from a Request URI for outgoing calls. It also removes the plus sign (+) from the "To" header and the "From" header. If the configuration file setting is set to NO, Mediation Server will not change the Request URI, the "To" header, or the "From" header.

Note that you will have to manually force the Mediation Server to strip of the + sign using the intelligently named configuration file “RemovePlusFromRequestURI”.


Update 952783 introduces functionality for Communications Server 2007 to remove the plus sign (+) from the "From" header when it is not E.164-compliant. If this action does not create an E.164-compliant number, Communications Server 2007 introduces a "P-Asserted-ID" header that has a phone-context value of "enterprise." This header enables the user lookup functionality in Communicator 2007. Additionally, Communications Server 2007 bypasses the server normalization logic if the header contains a phone-context value of "enterprise."

It’s good to see the list of Qualified PBXs expanding; now we can only hope that the Dual Forking scenarios will follow troop with Cisco and all the other vendors who has promised to deliver Interop (E.g. Alcatel, Avaya, Ericsson, Mitel, NEC and Siemens).

OCS Patches for Nortel CS1000 rel 5.5 with MCM 3.5 integration

MS Goodies - Sat, 2008-09-06 12:21

I recently updated our lab environment and it is now running Windows Server 2008 and Hyper-V. During that process we finally updated our test CS100o to rel 5.5 and that required some updates that are different from the ones listed on the MS UC OIP site (Which are also outdated both 943083 and 943085 has been superseeded) and the ones listed in the Nortel documentation for rel. 5.5 .

In the following I have listed the "Required" patches according to Nortel's documentation and the "Actual" based on the current version of the hotfixes

OCS 2007 Front End
Required - Standard Edition RTM version 6362.0 plus hotfix KB 942872
Actual – Standard Edition RTM version 6362 plus hotfix 945055 (Includes Apiem.dll and Sipstack.dll in version 3.0.6362.17, which 942872 introduces)

Office Communication Server 2007, Mediation Server
Required - December 17, 2007, Version 3.0.6362.36 plus hotfix KB943086 and KB944285
Actual - December 17, 2007, Version 3.0.6362.36 plus hotfix KB943086 and KB944285

OCS Application Proxy Server
Required - OCS 2007 – Standard Edition RTM version 6362.0 plus hotfix KB 942872
Actual – Standard Edition RTM version 6362 plus hotfix 945055 (Includes Apiem.dll and Sipstack.dll in version 3.0.6362.17, which 942872 introduces)

Office Communicator 2007 Client
Required - December 17, 2007, Version 2.0.6362.36 plus hotfix KB 943083
Actual - December 17, 2007, Version 2.0.6362.64 including hotfix KB 951662 that supersedes 943083 (And replaces all files in 6362.65 version)

NativeConsole.cs - Run console apps and get their output

Huddled Masses - Fri, 2008-09-05 11:53

To those of you who are not software developers: feel free to skip this post ;-)

A while ago I wrote a little class for calling console apps from a .Net application, and I’ve been using it in several of my apps (most notably in PoshConsole) and it works great, but since the only place I’ve really published it is in PoshConsole, I thought I’d write it up here, and share it with you …

Basically, it’s a slick invisible event-based wrapper around the Windows native console. What I mean is, it calls AllocConsole when it’s instantiated to create a native console, and hides the console window so it doesn’t show up. This allows you to run any console app you need to from within your app without having it popup a black window ;) Note this doesn’t let you run graphical consoles like EDIT.COM, but it can handle interactive apps like cmd.exe, batch files, or ftp.exe). All you really have to do is create one of my NativeConsole objects, handle its WriteOutputLine and WriteErrorLine events … and use its WriteInput method to send input or commands to the console app.

You can check out how it works in my WPF-based PoshConsole, and you can get the latest version of it from that project as well (it’s in \trunk\Huddled\Interop\NativeConsole.cs) but for now, here’s the single file source code, with a more liberal set of licenses than I allow for PoshConsole.


// Copyright (c) 2008 Joel Bennett

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// *****************************************************************************
// NOTE: YOU MAY *ALSO* DISTRIBUTE THIS FILE UNDER ANY OF THE FOLLOWING LICENSES:
// BSD:   http://opensource.org/licenses/bsd-license.php
// MIT:   http://opensource.org/licenses/mit-license.html
// Ms-PL: http://opensource.org/licenses/ms-pl.html
// GPL 2: http://opensource.org/licenses/gpl-2.0.php

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Text;

namespace Huddled.Interop
{

   /// <summary>
   /// A wrapper around AllocConsole, with some nice eventing to handle
   /// </summary>
   public class NativeConsole : IDisposable
   {
      /// <summary>
      /// The API/Interop/PInvoke methods for the NativeConsole
      /// </summary>
      internal class NativeMethods
      {

         #region  Fields (5)

         public const UInt32 DUPLICATE_SAME_ACCESS = 0x00000002;
         public const int LWA_ALPHA = 0x2;
         public const int LWA_COLORKEY = 0x1;
         public const int WS_EX_LAYERED = 0x80000;
         public const int WS_EX_TRANSPARENT = 0x00000020;

         #endregion

         #region  Enums (3)

         public enum ShowState : int
         {
            SW_HIDE = 0
            /// and lots of others
         }
         public enum GwlIndex : int
         {
            Id = (-12),
            Style = (-16),
            ExStyle = (-20)
         }
         public enum StdHandle : int
         {
            /// <summary>
            /// The standard input device
            /// </summary>
            INPUT_HANDLE = -10, //(DWORD)-10    The standard input device.
            /// <summary>
            /// The standard output device.
            /// </summary>
            OUTPUT_HANDLE = -11, //(DWORD)-11   The standard output device.
            /// <summary>
            /// The standard error device.
            /// </summary>
            ERROR_HANDLE = -12 //(DWORD)-12  The standard error device.
         }

         #endregion

         #region  Methods (13)

         //  Public Methods (13)

         [DllImport("kernel32")]
         [return: MarshalAs(UnmanagedType.Bool)]
         public static extern bool AllocConsole();

         [DllImport("kernel32.dll", SetLastError = true)]
         [return: MarshalAs(UnmanagedType.Bool)]
         public static extern bool CloseHandle(IntPtr hHandle);

         [DllImport("kernel32.dll", SetLastError = true)]
         [return: MarshalAs(UnmanagedType.Bool)]
         public static extern bool CreatePipe(out IntPtr hReadPipe, out IntPtr hWritePipe,
                                    ref SECURITY_ATTRIBUTES lpPipeAttributes, uint nSize);

         [DllImport("kernel32.dll", SetLastError = true)]
         public static extern bool DuplicateHandle(IntPtr hSourceProcessHandle,
            IntPtr hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr lpTargetHandle,
            uint dwDesiredAccess, bool bInheritHandle, uint dwOptions);

         [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
         [return: MarshalAs(UnmanagedType.Bool)]
         public static extern bool FreeConsole();

         [DllImport("kernel32.dll")]
         public static extern IntPtr GetConsoleWindow();

         [DllImport("user32.dll", SetLastError = true)]
         public static extern int GetWindowLong(IntPtr hWnd, GwlIndex nIndex);

         [DllImport("kernel32.dll", SetLastError = true)]
         public static extern bool ReadFile(
             IntPtr hFile,                   // handle to file
             byte[] lpBuffer,                // data buffer
             int nNumberOfBytesToRead,       // number of bytes to read
             out int lpNumberOfBytesRead,    // number of bytes read
             IntPtr overlapped               // overlapped buffer
             );

         [DllImport("user32.dll")]
         public static extern bool SetLayeredWindowAttributes(IntPtr hwnd, int crKey,
                                                            byte bAlpha, int dwFlags);

         [DllImport("kernel32.dll")]
         [return: MarshalAs(UnmanagedType.Bool)]
         public static extern bool SetStdHandle(StdHandle nStdHandle, IntPtr hHandle);

         [DllImport("user32.dll")]
         public static extern int SetWindowLong(IntPtr hWnd, GwlIndex nIndex, int dwNewLong);

         [DllImport("user32.dll")]
         [return: MarshalAs(UnmanagedType.Bool)]
         public static extern bool ShowWindow(IntPtr hWnd, ShowState nCmdShow);

         [DllImport("kernel32.dll", SetLastError = true)]
         public static extern int WriteFile(IntPtr hFile, byte[] buffer,
           int numBytesToWrite, out int numBytesWritten, IntPtr lpOverlapped);

         #endregion

         [StructLayout(LayoutKind.Sequential)]
         public struct SECURITY_ATTRIBUTES
         {
            public int nLength;
            public IntPtr lpSecurityDescriptor;
            [MarshalAs(UnmanagedType.Bool)]
            public bool bInheritHandle;
         }
      }

      public class OutputEventArgs
      {
         public string Text;
      }

      #region Delegate and Events (3)
      // Delegate, I changed this to be compatible with normal wpf/forms events
      public delegate void OutputDelegate(object source, OutputEventArgs args);

      // Events (2)
      public event OutputDelegate WriteErrorLine;
      public event OutputDelegate WriteOutputLine;
      #endregion

      #region  Private Fields (14)
      // Track whether Dispose has been called.
      private bool disposed = false;
      // A nice handle to our console window
      private IntPtr handle;
      // And our process
      private System.Diagnostics.Process process;
      // Our two threads
      private Thread outputThread, errorThread;
      // and the original handles to the console
      private IntPtr stdOutRead, stdOutWrite, stdInRead, stdInWrite, stdErrRead, stdErrWrite;
      // and the copy handles ...
      private IntPtr stdOutReadCopy, stdInWriteCopy, stdErrReadCopy;
      #endregion

      #region  Constructors and Destructors (2)
      /// <summary>Initializes a new instance of the <see cref="NativeConsole"/> class.
      /// </summary>
      public NativeConsole()
      {
         // Make ourselves a nice console
         NativeMethods.AllocConsole();
         // hide the window ...
         handle = NativeMethods.GetConsoleWindow();
         NativeMethods.ShowWindow(handle, NativeMethods.ShowState.SW_HIDE);
         //NativeMethods.SetWindowLong(handle, NativeMethods.GwlIndex.ExStyle,
         // (NativeMethods.GetWindowLong(handle, NativeMethods.GwlIndex.ExStyle) |
         // NativeMethods.WS_EX_LAYERED | NativeMethods.WS_EX_TRANSPARENT));
         //NativeMethods.SetLayeredWindowAttributes(handle, 0, 0, NativeMethods.LWA_ALPHA);

         process = System.Diagnostics.Process.GetCurrentProcess();


         NativeMethods.SECURITY_ATTRIBUTES saAttr;

         // Set the bInheritHandle flag so pipe handles are inherited.
         saAttr.nLength = Marshal.SizeOf(typeof(NativeMethods.SECURITY_ATTRIBUTES));
         saAttr.bInheritHandle = true;
         saAttr.lpSecurityDescriptor = IntPtr.Zero;


         // The steps for redirecting STDOUT:
         // * Create anonymous pipe to be STDOUT for us.
         // * Set STDOUT of our process to be WRITE handle to the pipe.
         // * Create a (noninheritable) duplicate of the read handle, and...
         // * Close the inheritable read handle.
         if (!NativeMethods.CreatePipe(out stdOutRead, out stdOutWrite, ref saAttr, 0))
         {
            System.Diagnostics.Trace.TraceError("Couldn't create the STDOUT pipe");
         }
         if (!NativeMethods.SetStdHandle(NativeMethods.StdHandle.OUTPUT_HANDLE, stdOutWrite))
         {
            System.Diagnostics.Trace.TraceError("Couldn't redirect STDOUT!");
         }
         // Create noninheritable read handle and close the inheritable read handle.
         if (!NativeMethods.DuplicateHandle(process.Handle, stdOutRead, process.Handle,
                        out stdOutReadCopy, 0, false, NativeMethods.DUPLICATE_SAME_ACCESS))
         {
            System.Diagnostics.Trace.TraceError("Couldn't Duplicate STDOUT Handle");
         }
         NativeMethods.CloseHandle(stdOutRead);

         // For the output handles we need a thread to read them
         outputThread = new Thread(OutputThread);
         outputThread.SetApartmentState(ApartmentState.STA);
         outputThread.Start();

         // The steps for redirecting STDERR are the same:
         // * Create anonymous pipe to be STDERR for us.
         // * Set STDERR of our process to be WRITE handle to the pipe.
         // * Create a (noninheritable) duplicate of the read handle and
         // * Close the inheritable read handle.
         if (!NativeMethods.CreatePipe(out stdErrRead, out stdErrWrite, ref saAttr, 0))
         {
            System.Diagnostics.Trace.TraceError("Couldn't create the STDERR pipe");
         }
         if (!NativeMethods.SetStdHandle(NativeMethods.StdHandle.ERROR_HANDLE, stdErrWrite))
         {
            System.Diagnostics.Trace.TraceError("Couldn't redirect STDERR!");
         }
         // Create noninheritable read handle and close the inheritable read handle.
         if (!NativeMethods.DuplicateHandle(process.Handle, stdErrRead, process.Handle,
            out stdErrReadCopy, 0, false, NativeMethods.DUPLICATE_SAME_ACCESS))
         {
            System.Diagnostics.Trace.TraceError("Couldn't Duplicate STDERR Handle");
         }
         NativeMethods.CloseHandle(stdErrRead);

         // For the output handles we need a thread to read them
         errorThread = new Thread(ErrorThread);
         errorThread.SetApartmentState(ApartmentState.STA);
         errorThread.Start();

         // The steps for redirecting STDIN:
         // * Create anonymous pipe to be STDIN for us.
         // * Set STDIN of our process to be READ handle to the pipe.
         // * Create a (noninheritable) duplicate of the WRITE handle and
         // * Close the inheritable WRITE handle.

         if (!NativeMethods.CreatePipe(out stdInRead, out stdInWrite, ref saAttr, 0))
         {
            System.Diagnostics.Trace.TraceError("Couldn't create the StdIn pipe");
         }
         if (!NativeMethods.SetStdHandle(NativeMethods.StdHandle.INPUT_HANDLE, stdInRead))
         {
            System.Diagnostics.Trace.TraceError("Couldn't redirect StdIn!");
         }
         // Create noninheritable read handle and close the inheritable read handle.
         if (!NativeMethods.DuplicateHandle(process.Handle, stdInWrite, process.Handle,
               out stdInWriteCopy, 0, false, NativeMethods.DUPLICATE_SAME_ACCESS))
         {
            System.Diagnostics.Trace.TraceError("Couldn't Duplicate StdIn Handle");
         }
         NativeMethods.CloseHandle(stdInWrite);
      }

      /// <summary>Releases unmanaged resources and performs other cleanup operations
      /// before the <see cref="Console"/> is reclaimed by garbage collection.
      /// Use C# destructor syntax for finalization code.
      /// This destructor will run only if the Dispose method does not get called.
      /// </summary>
      /// <remarks>NOTE: Do not provide destructors in types derived from this class.
      /// </remarks>
      ~NativeConsole()
      {
         // Instead of cleaning up in BOTH Dispose() and here ...
         // We call Dispose(false) for the best readability and maintainability.
         Dispose(false);
      }

      #endregion

      #region Methods (5)

      //  Public Methods (2)

      /// <summary>
      /// Implement IDisposable
      /// Performs application-defined tasks associated with
      /// freeing, releasing, or resetting unmanaged resources.
      /// </summary>
      public void Dispose()
      {
         // This object will be cleaned up by the Dispose method.
         // Therefore, we call GC.SupressFinalize to tell the runtime
         // that we dont' need to be finalized (we would clean up twice)
         GC.SuppressFinalize(this);

         Dispose(true);
      }

      /// <summary>
      /// Writes the input.
      /// </summary>
      /// <param name="input">The input.</param>
      public void WriteInput(string input)
      {
         byte[] bytes = System.Text.UTF8Encoding.Default.GetBytes(input);
         int written;

         int hresult = NativeMethods.WriteFile(stdInWriteCopy, bytes,
                                 bytes.Length, out written, IntPtr.Zero);
         if (hresult != 1)
         {
            throw new Exception("Error Writing to StdIn, HRESULT: " + hresult.ToString());
         }
      }

      //  Private Methods (3)

      /// <summary>
      /// Handles actual cleanup actions, under two different scenarios
      /// </summary>
      /// <param name="disposing">if set to <c>true</c> we've been called directly or
      /// indirectly by user code and can clean up both managed and unmanaged resources.
      /// Otherwise it's been called from the destructor/finalizer and we can't
      /// reference other managed objects (they might already be disposed).
      ///</param>
      private void Dispose(bool disposing)
      {
         // Check to see if Dispose has already been called.
         if (!disposed)
         {
            try
            {
               // // If disposing equals true, dispose all managed resources ALSO.
               if (disposing)
               {
                  errorThread.Abort();
                  outputThread.Abort();
                  //WriteInput("\n");

                  byte[] bytes = System.Text.UTF8Encoding.Default.GetBytes("\n" + (char)26);
                  int written;
                  NativeMethods.WriteFile(stdErrWrite, bytes, bytes.Length,
                                                      out written, IntPtr.Zero);
                  NativeMethods.WriteFile(stdOutWrite, bytes, bytes.Length,
                                                      out written, IntPtr.Zero);
                  //errorThread.Join();
                  //outputThread.Join();
               }

               // Clean up UnManaged resources
               // If disposing is false, only the following code is executed.
               NativeMethods.FreeConsole();
               //NativeMethods.CloseHandle(stdOutWrite);
               //NativeMethods.CloseHandle(stdOutReadCopy);
               //NativeMethods.CloseHandle(stdErrWrite);
               //NativeMethods.CloseHandle(stdErrReadCopy);
               NativeMethods.CloseHandle(stdInWriteCopy);
               NativeMethods.CloseHandle(stdInRead);
            }
            catch (Exception e)
            {
               Trace.WriteLine(e.Message);
               Trace.WriteLine(e.StackTrace);
               throw;
            }

         }
         disposed = true;
      }

      /// <summary>
      /// The ErrorThread ThreadStart delegate
      /// </summary>
      private void ErrorThread()
      {
         int BytesRead;
         byte[] BufBytes = new byte[4096];
         // consider wrapping this in a System.IO.FileStream
         try
         {
            while (NativeMethods.ReadFile(stdErrReadCopy, BufBytes, 4096,
                                                      out BytesRead, IntPtr.Zero))
            {
               if (WriteErrorLine != null)
               {
                  WriteErrorLine(this, new OutputEventArgs {
                     Text = UTF8Encoding.Default.GetString(BufBytes, 0, BytesRead) });
               }
            }
         }
         catch (ThreadAbortException) { }
         finally
         {
            NativeMethods.CloseHandle(stdErrWrite);
            NativeMethods.CloseHandle(stdErrReadCopy);
         }
      }

      /// <summary>
      /// The OutputThread ThreadStart delegate
      /// </summary>
      private void OutputThread()
      {
         int BytesRead;
         byte[] BufBytes = new byte[4096];
         // consider wrapping this in a System.IO.FileStream
         try
         {
            while (NativeMethods.ReadFile(stdOutReadCopy, BufBytes, 4096,
                                                      out BytesRead, IntPtr.Zero))
            {
               if (WriteOutputLine != null)
               {
                  WriteOutputLine(this, new OutputEventArgs {
                     Text = UTF8Encoding.Default.GetString(BufBytes, 0, BytesRead) });
               }
            }
         }
         catch (ThreadAbortException) { }
         finally
         {
            NativeMethods.CloseHandle(stdOutWrite);
            NativeMethods.CloseHandle(stdOutReadCopy);
         }
      }
      #endregion
   }
}

 
Categories: MS Scripting, powershell

Where does the * go?

jaredpar's WebLog - Thu, 2008-09-04 05:00

This is a more amusing than functional debate I enter into from time to time.  On a line where you declare a pointer type in C++, where should the * go? 

  1. Next to the type (i.e. Type* p1;)
  2. Next to the variable name  (i.e. Type *p1;)
  3. Who cares

For the moment lets ignore #3 (after all they don't care).  I'm a firm believer in #1.  After all * is a part of the type of the variable, not the name and therefore should be closer to the type. 

#2 believers disagree with this notion.  They believe the * is a part of the individual variable's type and not the actual type.  This is technically correct and can be demonstrated with the following code

Type* p1, p2;

The type of p2 is of course Type and not Type*. Therefore they argue, #2 is the superior way

This is true but I'm also a firm believer in don't declare multiple variables in a single declaration statement while coding in C++ unless the type has a user defined constructor.  Namely to avoid situations just like this. 

Categories: MS Scripting

F# CTP First Impressions

jaredpar's WebLog - Wed, 2008-09-03 05:00

I had a little bit of time this weekend to download the F# CTP.  The IDE portion of the CTP is a huge improvement over the previous CTP.  In particular the intellisense engine feels much more smooth, is available in new places and has much better results.  Project engine also has better integration.  Debugging support is much better. 

Overall the IDE now really feels like a ... well IDE.  I felt like the previous CTP was forced into Visual Studio and had much more in common with the old C++ IDE than VB and C#.  This time around the IDE is just more smooth and more closely resembles other managed integrations.  Definately worth the upgrade.

Categories: MS Scripting

A Lesson in Serialization

jaredpar's WebLog - Tue, 2008-09-02 05:00

A few days ago, I recklessly added a [Serialization] attribute to a few of my immutable collection types.  I needed to pass data between AppDomain's and adding [Serialization] was the quick and dirty fix.  Compiled, ran and I didn't think much about it. 

Luckily I was updating some unit tests last night and I remembered this and added a couple of serialization sanity tests.  Most of the tests passed first time but for my ImmutableStack class[1] was throwing an exception.  Well, it was actually my ImmutableQueue but it was failing in one of the inner ImmutableStack instances.  The test code was fairly straight forward

var stack = ImmutableStack.Create(new int[] { 1, 2, 3 }); using (var stream = new MemoryStream()) { var f = new BinaryFormatter(); f.Serialize(stream,stack); stream.Position = 0; var obj = f.Deserialize(stream); var stack2 = (ImmutableStack<int>)obj; var stack3 = stack2.Reverse(); }

I did a bit of digging and discovered the exception was coming from the stack2.Reverse() call.  Jumped through the code and didn't see much wrong.  I had several existing tests around ImmutableStack.Reverse() and I couldn't see why Serialization would make any difference. 

public ImmutableStack<T> Reverse() { var r = ImmutableStack<T>.Empty; var current = this; while (current != ImmutableStack<T>.Empty) { r = r.Push(current.Peek()); current = current.Pop(); } return r; }

Can you see what's wrong with the code?

It took me a few minutes of debugging and frustration.  The bug is in the while loop conditional.  Until you introduce serialization this code is just fine.  ImmutableStack<T>.Empty is a static readonly declaration.  The code implementation only allows for one to be created so it a singleton and equality can be done with a quick reference check.

private static readonly EmptyImmutableStack s_empty = new EmptyImmutableStack(); public static ImmutableStack<T> Empty { get { return s_empty; } }

Unfortunately serialization breaks the assumption that EmptyImmutableStack is a singleton.  The EmptyImmutableStack class is a singleton by convention only.  It's a private nested class that's only instantiated once per AppDomain.  There is nothing stopping the CLR or Serialization for that matter from creating a second instance.  In the case of deserialization that's exactly what happens.  The serializer isn't built to recognize this pattern and instead simply creates a new instance of EmptyImmutableStack upon deserialization. 

This essentially prevents you from safely using a functional style Empty pattern inside a serializable collection. 

The fix is simple enough, alter the conditional to be (!current.IsEmpty). 

[1] The version of ImmutableStack I'm using is heavily based off of Eric Lippert's implementation.

Categories: MS Scripting

Operations Manager 2007 Command Shell Examples

Jonathan Almquist - Mon, 2008-09-01 21:09

Thought I'd put together some samples of PowerShell commands for Operations Manager 2007.  It is assumed you are running these from the Operations Manager 2007 Command Shell (or all OpsMgr shap-ins are loaded).  Watch out for word wrap.  Any text in red needs to be modified to your criteria.  Check back now and then, as I will be adding to this list periodically.

FYI:  I don't claim to be a PowerShell guru.  Some of these could be reworked to run more efficiently, particularly when using in large-scale deployments.

 

Overrides

 

Get all overrides in Management Group:

Get-ManagementPack | where {$_.sealed -match "False"} | get-override | select-object name,parameter,module,rule,enforced,value,timeadded,lastmodified

 

Get all overrides in specific Management Pack:

Get-ManagementPack | where {$_.DisplayName -match "MP_Name"} | get-override | select-object Name,Rule,Monitor

 

Get all overrides that were created in a specific date/time range:

Get-ManagementPack | where {$_.sealed -match "False"} | get-override | where {$_.TimeAdded -ge "01/01/2008 00:00:00" -and $_.TimeAdded -lt "09/01/2008 23:59:59"} | select-object name,TimeAdded

 

Get all overrides that have been modified:

Get-ManagementPack | where {$_.sealed -match "False"} | get-override | where {$_.LastModified -gt $_.TimeAdded} | select-object name,TimeAdded,LastModified

 

Get all overrides that have been modified in a specific date/time range:

Get-ManagementPack | where {$_.sealed -match "False"} | get-override | where {$_.LastModified -gt $_.TimeAdded -and $_.LastModified -ge "01/01/2008 00:00:00" -and $_.LastModified -lt "09/01/2008 23:59:59"}  | select-object name,TimeAdded,LastModified

 

Get all rules overridden from specific Management Pack:

$overrides = Get-ManagementPack | where {$_.DisplayName -match "Override_MP_Name"} | get-override

$rules = $overrides | where {$_.rule}

foreach ($rule in $rules) {get-rule | where {$_.Id -eq $rule.rule.id} | select-object DisplayName}

 

Get all monitors overridden from specific Management Pack:

$overrides = Get-ManagementPack | where {$_.DisplayName -match "Override_MP_Name"} | get-override

$Monitors = $overrides | where {$_.monitor}

foreach ($monitor in $monitors) {get-monitor | where {$_.Id -eq $monitor.monitor.id} | select-object DisplayName}

 

Agent

 

Get all agents currently reporting to specific Management Server
(this needs to be run on target management sever, as it queries local IP properties)

$ip = [Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties()

$active = $ip.GetActiveTcpConnections()

$connectedAgents = $active | where {$_.LocalEndPoint -match "5723"}

$agents = get-agent

foreach ($RemoteEndPoint in $connectedAgents)
{$agents | where {$_.ipaddress -eq $RemoteEndPoint.RemoteEndPoint.Address.IPAddressToString} | select-object DisplayName}
write-host "`n`nAgents connected to this Management Server:" $connectedAgents.count

 

Approve or Reject specific agent for manual install:

$action = Get-AgentPendingAction | where {$_.AgentName –match “netbios_name” -and $_.AgentPendingActionType –match "ManualApproval”}

$action | [approve or reject]-AgentPendingAction

OCS 2007 R2 will be 64 bit

MS Goodies - Mon, 2008-09-01 09:25

So it is official now. Office Communications Server 2007 R2 (Wave 13) will support 64 bit OS as the only Operating System (So no 32 bit support).

Within the MVP community there has been a lot of discussion about the good/bad in this design decision, but personally I think that most of our customers are 64-bit ready due to Exchange 2007 and in general won't see this a big issue. Yes, it will mean that we will have to migrate our servers, but as a consultant I would (almost) never suggest using in-place upgrades anyway.

What is your opinion about this ?

Read more here Next release of OCS to support 64 Bit OS (x64).

F# CTP Released

jaredpar's WebLog - Fri, 2008-08-29 12:30

A new version of the F# CTP was released today.  There are a lot of new improvements to the language and project system.  Check it out here

Categories: MS Scripting

Disabling JIT optimizations while debugging

jaredpar's WebLog - Fri, 2008-08-29 05:00

If you've ever been debugging a managed app, only to be unable to evaluate any of the locals or parameters because the code was "optimized", check out the article below.  It shows a quick trick to disable optimizations by way of a .ini file.  This is great because it doesn't force you to recompile the application and takes only seconds to implement.

The short version is create an .ini file (i.e. myapp.ini) with the following contents.

[.NET Framework Debugging Control] GenerateTrackingInfo=1 AllowOptimize=0

This has really saved me time debugging recently.  It's been blogged about by several others but given that I've had to search for this solution 3 times in as many weeks, I figured blogging about it would make it easier to find next time :)

http://msdn.microsoft.com/en-us/library/9dd8z24x.aspx

Categories: MS Scripting

Google Charts from PowerShell - Part 1

Huddled Masses - Thu, 2008-08-28 11:45

Several people have blogged about using the Google charts api from PowerShell, but everyone seems to be using the “simple” numerical encoding, so I figured that as the first step of my own google chart api wrapper module I would start out by writing up a simple encoder. I’m not posting this to the script repository until I’m done with it — this is just the number encoding function.

But I figured I’d blog it here in case it will help anyone else write the full wrapper module “for” me before I get around to it :) In any case, remember this doesn’t encode numbers higher than 4095, so if you have a bunch of numbers and some of them might be larger than that, you’ll still need to normalize them so they are within that range. I’ll post the function to normalize a series of numbers later this evening, because for some reason I can’t find it right now, but I’m sure I already wrote it ;).


## Google Chart API extended value encoding function
#########################################################################
function GoogleEncode {
BEGIN {
   ## Google's odydecody is a 64 character array
   $ody = "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q",
   "R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j",
   "k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","0","1","2",
   "3","4","5","6","7","8","9","-","."

   ## The actual filter function
   filter encode {
      # we have a hard-coded "overflow" value
      if($_ -ge ($ody.Count * $ody.Count) ) { return "__" }
     
      $y = -1  # $y is a ref variable, so it has to be defined
      $x = [Math]::DivRem( $_, $ody.Count, [ref]$y )
      return "$($ody[$x])$($ody[$y])"
   }
   
   ## Handle numbers as parameters
   foreach($i in $args) {
      $i | encode
   }
}
## Or handle numbers from the pipeline. We don't care :-)
PROCESS {
   if($_ -ne $null) { $_ | encode }
}
}
 

That’s the whole thing … it’s really only about three lines of code (including the definition of $ody), but the rest is necessary to make it handle parameters or pipeline values. :D

Categories: MS Scripting, powershell

5 things Hollywood thinks computers can do

jaredpar's WebLog - Wed, 2008-08-27 05:05

Reading another Jtenos' blog, I came across this article about things Hollywood thinks can be done with computers.  Humorous read.

http://www.cracked.com/article_15229_5-things-hollywood-thinks-computers-can-do.html

Categories: MS Scripting

Comments

jaredpar's WebLog - Tue, 2008-08-26 05:00

If only people spent as much time writing comments as they did speaking to the evils of comments.  Everything from useless, inaccurate, to many comments make code unreadable, you should code better ... etc. 

I haven't ever looked at a piece of code and thought "wow, way too many comments" or "that code would be beautiful if it weren't for the comments."

Do the next guy a favor, comment your code. 

Categories: MS Scripting
Syndicate content