Showing posts with label .NET. Show all posts
Showing posts with label .NET. Show all posts

Friday, February 23, 2018

PowerShell’s $OFS built-in Variable And What It Does

The other day, I was working on converting some C'# to PowerShell. 95% was trivial and almost muscle memory. Then I came to this block of C#

char[] chars = { 'w', 'o', 'r', 'd' };
string string1 = new string(chars);
Console.WriteLine(string1);

The output is:

word

So I initially translated it as:

[char[]] $Chars =  ('w', 'o', 'r', 'd' )
[String $String1 = $Chars
Write-Host $String1

But that produced:

w o r d

The same characters but with spaces between which seemed illogical (at first!). I scratched my head, and did a bit of digging over at Spiceworks, where I was introduced to the $OFS PowerShell Variable. $OFS holds a string, known as the Output Field Separator.   PowerShell uses this character string to separate array elements when it coverts the array to the string, PowerShell has a default value of  ” ”, but you can change at the command line, in a script, or in your Profile. The issue here is that PowerShell is doing the array to string conversion and separates each character in the char array with the separator (“ “). You can read a bit more about this in an old blog post by Jeffrey Snover:

This gave rise to two solutions. The first is to let .NET do the conversion and the second was to leverage $OFS. Here  are two ways to do it: https://blogs.msdn.microsoft.com/powershell/2006/07/15/psmdtagfaq-what-is-ofs/


# Leveraging $OFS
[char[]] $Chars =  ('w', 'o', 'r', 'd' )
$OFS = ''  # Set separator to null
[String] $String1 = $Chars
Write-Host $String1
# Or using .NET directly
[char[]] $chars =  ('w', 'o', 'r', 'd' )
$String2 = [System.String]::New($Chars)
Write-Host $string2

This is interesting, but there is a highly practical solution to an issue I’ve seen brought up in several PowerShell support places. The issue if how to construct a comma separated string of words. So if you had an array of several words such as (‘X423q420’, ‘JG75-01-27’,”PCNY”) you could easily concatenate them as follows:

$Array = (‘X423q420’, ‘JG75-01-27’,”PCNY”)
[string] $Array

Which produces:


X423q420,JG75-01-27,PCNY

You could also create the array from properties then force it to be separated by $OFS, like so:

$F = Get-ChildItem –Path X.XML
$OFS = ','
$Sring3 = [string] ($F.Fullname, ($f.length/1kb).ToString('n3'))
Write-Host $String3

Which produces this:

C:\foo\X.XML,0.317

You learn something nearly every day!




Wednesday, November 12, 2014

Microsoft takes .NET Open Source AND Cross-Platform

Microsoft has this week announced that it is providing the full .NET Server stack into Open Source. This includes ASP.NET, the .NET compiler, the .NET Core Runtime including the Framework and Libraries. This Microsoft says this should enable "developers to build with .NET across Windows, Mac or Linux".  For the details, see http://go.microsoft.com/fwlink/?LinkId=518340

And as if that were not enough Open Source goodness, Microsoft also announced Visual Studio Community 2013 – a free, fully featured version of Visual Studio including full extensibility.  Developers, or anyone else interested, can get started with Visual Studio Community 2013 HERE.

Wow!

Technorati Tags: ,

Monday, November 10, 2014

Writing Classes With PowerShell V5-Part 1

As I noted in previous blog posts (here and here) one of the many cool features coming with PowerShell V5 is the ability to develop Classes and Enums using PowerShell. in Monday's blog post, I showed how you could create an Enum, one important construct useful to creating classes.

Before I look at creating classes with PowerShell V5, it might make sense to go over what a class is and what creating them means. Many PowerShell users may be under familiar with the concepts involved.

Classes

The first thing to cover is classes. But what IS a class? A class is the definition of an object. In PowerShell everything you do relates to instances of objects that belong to some class. If you issue Get-ChildItem on the file system provider, you get zero, one, or more object occurrences, or instances, of either the System.Io.DirectoryInfo or System.Io.FileInfo classes. The number 42 is an object of the class System.Int32,

The Class defines the object (and occurrences of that object). Each class has a number of members. These include constructors, properties, and methods. The constructor is how you create a new class instance (creating a System.Io.Fileinfo object (instance) pointing to c:\foo.bar.ps1). Properties are attributes of object are actions you can apply to the object, such as the name of a file. The  properties and methods of a class can be either static (belonging to the class) or dynamic (belonging to a class instance). This is a difference new PowerShell – see below for more on the difference.

Constructors

A constructor is code that creates a new instance of the class. Constructors can take parameters that describe the object instance to be created. You can also overload constructors – creating more than one constructor with different sets of parameters. In the System.Net.Mail.MailMessage class, you can see 4 different constructors; one takes no parameters, while the other three take different sets of parameters, as you can see in MSDN. Each constructor creates an object instance (a mail message) but with different properties.

Properties

A properties is some attribute, either of the class itself or of an class instance. For example, the class [system.int32]. Each property has a type and this can be a value type (such as a string, or an integer) or a more complex object. An occurrence of the System.Net.Mail.MailMessage  class, for example, has a simple Priority property that takes a string (Low, High, Normal). It also has a property, To, which takes an object of the class System.Net.Mail.MailAddresss. The point here is that an object instance (a mail message) has a property (to) that itself is an object which has properties (e.g. DisplayName). Of course, that property too could be an object etc etc (although in the case of System.Net.MailAddress it doesn't!).

Methods

A method is some function that the class is capable of performing – either on an specific instance (a dynamic or instance method) or based on the class (a static method). Dynamic methods usually do something to the instance, while static methods do something that relates to class itself. The System.Int32 class, for example, has both static and instance based methods. Individual instances of the the System.Int32 class contain methods that convert the instance's value to another form (e.g. Boolean, or System.Int64, etc). Those dynamic methods work on the the instance of the class. The ToString method on instances of System.Int32 converts the value into a nicely formatted string, with the help of a CultureInfo object, like this:

image

Static Methods and Static Properties

One concept that many new-to-PowerShell folks find harder to understand is concept of static (vs dynamic of instance) methods and properties. A static method is a method that does not make use of a specific instance of the class. Instead it works by doing something class related. The System.Int32 class has a neat static method, Parse. The Parse method takes a string and either parses that string into a 32-bit number or raises an exception if it can't correctly parse the string.  The PowerShell Syntax to invoke a static method is: [<class name>]::methodname(<array of method parameters, or nothing>]. For example:

[System.Int32]::parse('42')

The System.Int32 class also has static properties or properties of the class. For example, MaxValue is the largest value that a System.Int32 can hold, while MinValue is the smallest value. In PowerShell, the Syntax for static properties is: [<class name>]::<propertyname>.

Here is an illustration of static methods and properties.

image

As you can see in this screen shot, the Parse method parses nicely the string '42' into a 32-bit integer. But the string ('4223452354234523452345235234'') could not be parsed and the Parse method threw an exception, the Overflow exception, as you can . You could use the Parse method inside a Try/Catch block to, for example, validate that some value passed in from a user is of the right form (i.e. a 32-bit integer) and catch and handle any exceptions to that validation.

A static property is some property related to the class not an instance. System.Int32 also also has some static properties, including MaxValue (the largest 32-bit integer), and MinValue (the smallest integer).

Creating Object Instances

PowerShell users typically create the object instance by using cmdlets (or functions, aka script cmdlets). Thus you use Get-ChildItem cmdlet and get instances of System.Io.FileInfo and/or System.Io.DirectoryInfo classes. In most cases, you process the objects instances by using cmdlets for example using Set-ADUser to update user information in Active Directory. Best practice says to use cmdlets where you can and only then drop down into lower level code.

There are three ways you can create new instances of an object (class). The first is via a cmdlet, but in the absence of cmdlets/functions, then you can either  use a static method of the class or use the New-Object cmdlet and specify the class of which you wish to create an instance. One example is the  class System.Guid, which it defines and manages guids. There are no cmdlets to manage this object type. If there had been, then you would most likely have a New-Guid cmdlet to create a new guid. Since that cmdlet does not exist, to create a new guid, you use a static method, like this:

.

image

The other way to create new instances is to use the New-Object cmdlet. This cmdlet uses the class constructors available and matches the parameters you specify with the various constructors. For example, you can create a new instance of the System.Mail.Mailmessage class using one of four constructors. To Create an empty mail message, you would do this:

# Create an empty massage
$EmptyMsg = New-Object System.Net.Mail.Mailmessage

# Create a message from and to
$To= '[email protected]'
$Fm='[email protected]'
$MailMsg = New-Object System.Net.Mail.MailMessage $Fm, $To

So What?

In Windows, Microsoft and other vendors have provided thousands of cmdlets, but as yet, there is not full coverage of all the objects in the .NET framework. Thus if you need to use objects of those types (belonging to some less well known .NET Class). A good example is localisation. If you want to present a price in say US$, Norwegian crowns and UK Pound sterling. Assuming you know how to use the ServiceEx web services, the script looks like this:

# Get Curency conversion rates
$From = 'GBP'
$Tous  = 'USD'
$Tono  = 'NOK'
$CurrencyConvertor = New-WebServiceProxy "
http://www.webservicex.net/CurrencyConvertor.asmx?WSDL"
$USrate = $currencyConvertor.ConversionRate($from,$tous)
$NOrate = $currencyConvertor.ConversionRate($from,$tono)

# Calculate price
$priceUK = 12345.669
$priceNO = $PriceUK * $NOrate
$priceUS = $PriceUK * $USrate

# Convert to nice strings
$usinfo = [System.Globalization.CultureInfo]::CreateSpecificCulture('en-us')
$Noinfo = [System.Globalization.CultureInfo]::CreateSpecificCulture('no-nb')

"The UK price is:  $($PriceUK.tostring('c'))"
"The NO price is:  $($priceNO.tostring('c',$noinfo))"
"The US price is:  $($priceUS.tostring('c',$usinfo))"

And the output looks like this:

image

Pretty easy, when you know how to manage .NET classes and can use XML web services. The .NET framework contains a wealth of classes that have value, depending what you are working with. Being able to just reach out and grab them, when there are no cmdlets, provides you with a lot of power. Plus, if you understand what is going on with objects, troubleshooting scripts becomes easier – if nothing else, the error messages may make a bit more sense.

In the next article I'll look at actually combining the information presented here with how to create these things using PowerShell V5.

 

Monday, January 27, 2014

Creating A Message Box Using PowerShell

The other day, a student asked me how he could display a message box as part of a script. There is no, out of the box, cmdlet that does this, she pointed out. What she wanted to do was to display a window, with a window title and some contents, like this:
image

Now if you are a .NET programmer, this is pretty much a no brainer – just call the Windows.Forms.Messagebox’s Show method, and provide the text and the heading. Easy – but what if you are using PowerShell? As a Lync Admin – you might have a script that, say, provisioned users and you want to display a nice friendly message box to tell the user some bit of information such as how many users were provisioned. So how do you do that?

PowerShell, as you all know (or probably should know) is based on .NET – many cmdlets are just a PowerShell wrapper around an existing .NET Class/method. For example, Get-Process just invokes the System.Diagnostic.Process class’s GetProcesses() method. Now the cmdlet does a little more than just a GetProcess call, such as processing wild cards, enabling the cmdlet to run against a different machine, etc. But essentially, the base cmdlets just enable IT Pros simple access into .NET functions and Features. Application specific cmdlets, such as those supported by Lync, provide access into application specific functions, which are implemented as .NET Classes too. You can think of the application specific classes as just an extension to .NET.

The .NET Framework, and the Application specific ‘extensions’, are vast. There are a very large number of classes in total, and many of them have no relevance at all to the tasks that Lync admins carry out. To load all the relevant classes at runtime each time you open PowerShell would be very wasteful – both in terms of how long it would take to load them all, plus the runtime overhead (i.e. memory) wasted on classes never used. Thus, PowerShell only loads a core set of classes by default. But there is nothing stopping you from first loading the using any other .NET class.

Each .NET class is delivered via a DLL. If you look at http://msdn.microsoft.com/en-us/library/system.diagnostics.process(v=vs.110).aspx, you can see the Systems.Diagnostics.Process class is implemented in the System.DLL (See ‘Assembly:’). System.DLL holds the core .NET functions and is always loaded by PowerShell. If you go to the http://msdn.microsoft.com/en-us/library/system.diagnostics.process(v=vs.110).aspx page, which documents the MessageBox class, you’ll see this class is contained in System.Windows.Forms DLL, which is NOT loaded by default.
So to use the class in the first place, we need to first load the DLLs. This is pretty easy and looks like this:
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
This load the DLL from .NET’s global assembly cache and it remains loaded in the current PowerShell  window and memory space till you close that instance of PowerShell. If you have other assemblies either part of the .NET Framework (e.g. System.Numerics) or a privately developed assembly, you can load them in a similar fashion.

Developers and PowerShell Gurus will probably point out that the LoadWithPartialName method has been deprecated. This is true but the recommended approach is more complex. Whatever,  it remains the case that the LoadWithPartialName method works, and is likely to continue to work for some time! You can read a good explanation of this in Lee Home’s blog (http://www.leeholmes.com/blog/2006/01/17/how-do-i-easily-load-assemblies-when-loadwithpartialname-has-been-deprecated/) although you should note that that article was written in the Monad days, and is just slightly out of date (e.g. it uses .MSH as an extension). But for now, using this deprecated method does work and as I say, is likely to continue to work for a while!

So once you have the DLL loaded, you can just use the normal .NET calling feature to invoke a method in a .NET class directly. The core PowerShell line of code to do this is:
[Windows.Forms.MessageBox]::Show($Message, $BoxTitle, 
   
[Windows.Forms.MessageBoxButtons]::OK , 
    [Windows.Forms.MessageBoxIcon]::Information)
Ok, so it’s three lines long but it is quite simple. But rather than have to load an assembly and call that nasty looking method, you can wrap all of this inside a simple Advanced Function, and load that in your Profile or as part of a script or suite of scripts. I’ve written a simple script that implements a Show-Message function that displays a message box as you see above – see my PowerShell scripts blog for the script.
The bottom line is that you can easily display a message box from your script if and where you need. Just leverage my script as part of your profile, a personal module or directly inside a longer script and go for it.

Wednesday, March 21, 2012

Finding The Folder the .NET Utilities Live in - Using PowerShell

I am playing around with some PowerShell V3 stuff and needed to use Ngen.exe to do a native generation of an assembly and move it to the Global Assembly Cache. So where is it? I could have wandered around in the Windows folder, but instead decided to ask .NET itself, using PowerShell.

The .NET class System.Runtime.InteropServices.RuntimeEnvironment contains several static methods that return information about the CLR environment.  There are three that are of possible interest to the IT Pro:

FromGlobalAccessCache – this static method tests an assembly to determine if it ewas loaded from the GAC.

GetRuntimeDirectory – this static method returns the folder name where the CLR was installed. This folder contains Ngen, the C# complier, and other .NET tools.

GetSystemVersion – this method returns the version number of the .NET Framework

 

From PowerShell Version 2, this looks like:

 

image

If you are using the beta version of PowerShell V3, you might see this:

image

File under: Interesting things you can do with .NET and PowerShell.

Monday, August 02, 2010

More on Using Different Versions of the .NET Framework

In yesterday’s blog post, I wrote about being able to use later versions of the .NET Framework with PowerShell. The trick was simple: create a config file, a small file of XML, to enable the use of, in my case, the .NET Framework Version 4 and the new namespace System.Numerics. That XML file tells PowerShell what version of the .NET Framework to load. You can see this if you display $psversiontable variable. By default, you’ll see something like this:

PSH [C:\foo]: $PSVersionTable

Name                           Value
----                           -----
CLRVersion                     2.0.50727.4200
BuildVersion                   6.0.6002.18111
PSVersion                      2.0
WSManStackVersion              2.0
PSCompatibleVersions           {1.0, 2.0}
SerializationVersion           1.1.0.1
PSRemotingProtocolVersion      2.1

But with the .Config file in place, you’d now see this:

PSH [C:\foo]: $PSVersionTable

Name                           Value
----                           -----
PSVersion                      2.0
PSCompatibleVersions           {1.0, 2.0}
BuildVersion                   6.0.6002.18111
PSRemotingProtocolVersion      2.1
WSManStackVersion              2.0
CLRVersion                     4.0.30319.1
SerializationVersion           1.1.0.1

Another key difference is that when you now load additional .NET namespaces using LoadWithPartialName, you will get later version of the dll (the exact version number loaded depends on what you put into the config file. So loading Windows Forms now looks like this:

 

PSH [C:\foo]: [system.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

GAC    Version        Location
---    -------        --------
True   v4.0.30319    C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Windows.Forms\v4.0_4.0.0.0__b77a5c…

By default, you got this:

PSH [C:\foo]: [system.Reflection.Assembly]::LoadWithPartialName("system.windows.forms")

GAC    Version        Location
---    -------        --------
True   v2.0.50727     C:\Windows\assembly\GAC_MSIL\System.Windows.Forms\2.0.0.0__b77a5c…

It’s pretty easy to use later versions of the .NET Framework. These later versions provide new classes you may find useful.

PSH [C:\foo]: [system.Reflection.Assembly]::LoadWithPartialName("system.windows.forms")

GAC    Version        Location
---    -------        --------
True   v2.0.50727     C:\Windows\assembly\GAC_MSIL\System.Windows.Forms\2.0.0.0__b77a5c561934e089\System.Windows.Forms.dll

But beware of doing this in a data centre without testing that your existing scripts are fully compatible with the later versions of the Framework. You shouldn’t have any problems as MS is pretty good about forward compatibility, but it never hurts to be careful.  Just ensure you do thorough testing before rolling this out across the board.

Technorati Tags: ,

Sunday, August 01, 2010

Using Newer Version(s) of .NET with PowerShell

I’ve been playing around a bit with the latest version of the .NET Framework. There are some pretty cool new classes and namespaces but one that caught my eye was System.Numerics. This namespace has two neat classes: System.Numerics.BigInteger and Sytem.Numerics.Complex – these represent big integers and complex numbers respectively. To demonstrate the BigIngteger class, I’ve written two small scripts: New-BigInteger.ps1 and Get-BigIntegerProperties.ps1 (with more to come!). You can get these and several hundred more PowerShell scripts from my Powershell Scripts blog. When I first started to develop these scripts, starting first to translate an MSDN sample from C# into  PowerShell, I came across some curious errors. In the end learned how to call updated versions of the .NET Framework.

By default, PowerShell uses .NET version 2.0. But if you want to use classes implemented in later versions of the Framework (in namespaces that are not loaded by default of course), you first need to load the relevant dll. You can do this as follows:

Add-Type -Path "C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Numerics.dll"

But there’s only one problem (by default!) – when you do this you get the following run time error:

Add-Type : Could not load file or assembly 'file:///C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Numerics.dll' or one of its dependencies. This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded.
At line:1 char:9
+ Add-Type <<<<  -Path "C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Numerics.dll"
    + CategoryInfo          : NotSpecified: (:) [Add-Type], BadImageFormatException
    + FullyQualifiedErrorId : System.BadImageFormatException,Microsoft.PowerShell.Commands.AddTypeCommand

The solution is pretty simple – just tell PowerShell to use a later version of the CLR. To do this, you need to create a config file, named PowerShell.Exe.Config, located in the same folder as PowerShell.Exe (and another one for PowerShellISE.Exe, or PowerShellISE.Exe.Config). These config files contain a small bit of XML to tell the system which version of the CLR to use. To access the .NET 4.0 versions, use the following:

<?xml version="1.0"?>
<configuration>
    <startup useLegacyV2RuntimeActivationPolicy="true">
        <supportedRuntime version="v4.0.30319"/>
        <supportedRuntime version="v2.0.50727"/>
    </startup>
</configuration>

With this XML created, just restart PowerShell and you can add the System.Numerics.Dll and use the classes in that namespace!

Sunday, January 18, 2009

Determining If An Object Is An Array

Over on Hal Rotettenberg’s blog (TechProsaic), he recently posted an interesting article about how to tell if an object in PowerShell is an array or a scalar. His solution was to use the Get-Type method, and to look for the BaseType property of the object. Like this:

PS C:\foo> $array = 1,2,3
PS C:\foo> $scalar = 1
PS C:\foo> $array.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

PS C:\foo> $scalar.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Int32                                    System.ValueType

Looking carefully at what the GetType method returns, there’s an “IsArray” property, as follows:

PS C:\foo> $a
1
2
PS C:\foo> $a.GetType().IsArray
True

Pretty cool and to some degree more .NET than an another approach I’ve used. In some scripts, I’ve just checked for the existance of the count property. An array has one, but a scalar doesn’t. I do something like this:

PS C:\foo> if ($a.count) {"array"} else {"scalar"}
array
PS C:\foo> if ($b.count) {"array"} else {"scalar"}
scalar

These three approaches (basetype, IsArray and checking for count) all work – they can help to determine whether an object (i.e. a PowerShell variable) is an array or just a scalar. However, this doesn’t always work. In particular, the approach does not give proper results if you are using COM objects. To show this problem, let’s take a look the Group Policy Management Console COM interface. In this example, I search for all the GPOs in my domain. There are currently just 4 GPOs – and these are returned. However, although checking the count works, the BaseType is not so helpful. Here’s a small script I wrote to demonstrate this

# Setup GPMC
$gpm  = new-object -com GPmgmt.Gpm
$k    = $gpm.getconstants()
$dom  = $gpm.getdomain("cookham.net", "","")   
# Search for all GPOs
$sc=$gpm.CreateSearchCriteria()
$gpos = $dom.SearchGPOs($sc)
# Now - result time
"Type         :{0}" -f $gpos.gettype()
"Base Type    :{0}" -f $gpos.gettype().basetype
If ($gpos.Count) {"Seems to be an array"} else {"Seems to be a scalar"}
"Count        :{0}" -f $gpos.Count
"An array?    :{0}" -f $gpos.gettype().IsArray

The results of this were a little surprising:

PS C:\foo> . 'C:\Users\tfl\AppData\Local\Temp\Untitled4.ps1'
Type         :System.__ComObject
Base Type    :System.MarshalByRefObject
Seems to be an array
Count        :4
An array?    :False

As you can see, the $GPOS object appears to be an array and has a count – but GetType says it’s not an array. ALso, the Type and BaseType don’t actually help all that much.

If I change the code above marginally (to search for just one GPO) as follows:

# Setup GPMC
$gpm  = new-object -com GPmgmt.Gpm
$k    = $gpm.getconstants()
$dom  = $gpm.getdomain("cookham.net", "","")   
# Search for one GPO
$sc=$gpm.CreateSearchCriteria()
#Add a searcher to search for just ONE GPO Object
$sc.add($k.SearchPropertyGPODisplayName,$k.SearchOpEquals, "GPO1")
# Now search
$gpos = $dom.SearchGPOs($sc)
# Now - result time
"Type         :{0}" -f $gpos.gettype()
"Base Type    :{0}" -f $gpos.gettype().basetype
If ($gpos.Count) {"Seems to be an array"} else {"Seems to be a scalar"}
"Count        :{0}" -f $gpos.Count
"An array?    :{0}" -f $gpos.gettype().IsArray

The results of this were even more surprising to me:

PS C:\foo> . 'C:\Users\tfl\AppData\Local\Temp\Untitled4.ps1'
Type         :System.__ComObject
Base Type    :System.MarshalByRefObject
Seems to be an array
Count        :1
An array?    :False

This time, although only one object was returned, the count property exists and it appears to be an array! I wonder if I was the only person to be marginally confused!

While the three techniques above work great for .NET objects, they don’t work well for COM Objects. You just have to know what the underlying API (COM, .NET, etc) returns. In the case of the GPMC, the APIs seem to always return a collection, even when there’s only one object occurrence returned. For most harder-core developers, this really is not an issue, but for Admins using PowerShell it can be very confusing (It took me several hours to work this out. It’s one of those things that if you are to use PowerShell richly, you just have to know.

Technorati Tags: ,,,,

Monday, December 15, 2008

.NET and PowerShell

This week, Jeffrey Snover has posted an excellent post, Explore Your [Environment], that examines both some of the details of the [System.Environment] class but also on how PowerShell integrates with .NET. As I said in a comment on the blog, I wish I’d seen this post many years ago, as I struggled in the early days to understand how you could reach into .NET with PowerShell.

As Jeffrey describes, the .NET class has thousands of types, or types of objects. For example, System.Int32, a 32-bit integer. To access this type in Powerhell, simply enclose the type name in square brackets, as follows:

PS C:\Users\tfl> [system.int32] IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Int32 System.ValueType

You can also pipe the class to Get-Member to discover some of the properties and methods this type supports, as follows:

PS C:\Users\tfl> [system.int32] | get-member TypeName: System.RuntimeType Name MemberType Definition ---- ---------- ---------- Clone Method System.Object Clone() Equals Method System.Boolean Equals(Object obj), System.Boolean Equals(Type o) FindInterfaces Method System.Type[] FindInterfaces(TypeFilter filter, Object filterCriteria) FindMembers Method System.Reflection.MemberInfo[] FindMembers(MemberTypes memberType, Binding... GetArrayRank Method System.Int32 GetArrayRank() GetConstructor Method System.Reflection.ConstructorInfo GetConstructor(BindingFlags bindingAttr,... GetConstructors Method System.Reflection.ConstructorInfo[] GetConstructors(BindingFlags bindingAt... GetCustomAttributes Method System.Object[] GetCustomAttributes(Boolean inherit), System.Object[] GetC... GetDefaultMembers Method System.Reflection.MemberInfo[] GetDefaultMembers() GetElementType Method System.Type GetElementType() GetEvent Method System.Reflection.EventInfo GetEvent(String name, BindingFlags bindingAttr... GetEvents Method System.Reflection.EventInfo[] GetEvents(BindingFlags bindingAttr), System.... GetField Method System.Reflection.FieldInfo GetField(String name, BindingFlags bindingAttr... GetFields Method System.Reflection.FieldInfo[] GetFields(BindingFlags bindingAttr), System.... GetGenericArguments Method System.Type[] GetGenericArguments() GetGenericParameterConstraints Method System.Type[] GetGenericParameterConstraints() GetGenericTypeDefinition Method System.Type GetGenericTypeDefinition() GetHashCode Method System.Int32 GetHashCode() GetInterface Method System.Type GetInterface(String fullname, Boolean ignoreCase), System.Type... GetInterfaceMap Method System.Reflection.InterfaceMapping GetInterfaceMap(Type ifaceType) GetInterfaces Method System.Type[] GetInterfaces() GetMember Method System.Reflection.MemberInfo[] GetMember(String name, MemberTypes type, Bi... GetMembers Method System.Reflection.MemberInfo[] GetMembers(BindingFlags bindingAttr), Syste... GetMethod Method System.Reflection.MethodInfo GetMethod(String name, BindingFlags bindingAt... GetMethods Method System.Reflection.MethodInfo[] GetMethods(BindingFlags bindingAttr), Syste... GetNestedType Method System.Type GetNestedType(String fullname, BindingFlags bindingAttr), Syst... GetNestedTypes Method System.Type[] GetNestedTypes(BindingFlags bindingAttr), System.Type[] GetN... GetObjectData Method System.Void GetObjectData(SerializationInfo info, StreamingContext context) GetProperties Method System.Reflection.PropertyInfo[] GetProperties(BindingFlags bindingAttr), ... GetProperty Method System.Reflection.PropertyInfo GetProperty(String name, BindingFlags bindi... GetType Method System.Type GetType(), System.Type GetType() InvokeMember Method System.Object InvokeMember(String name, BindingFlags bindingFlags, Binder ... IsAssignableFrom Method System.Boolean IsAssignableFrom(Type c) IsDefined Method System.Boolean IsDefined(Type attributeType, Boolean inherit) IsInstanceOfType Method System.Boolean IsInstanceOfType(Object o) IsSubclassOf Method System.Boolean IsSubclassOf(Type type) MakeArrayType Method System.Type MakeArrayType(), System.Type MakeArrayType(Int32 rank) MakeByRefType Method System.Type MakeByRefType() MakeGenericType Method System.Type MakeGenericType(Type[] instantiation) MakePointerType Method System.Type MakePointerType() ToString Method System.String ToString() Assembly Property System.Reflection.Assembly Assembly {get;} AssemblyQualifiedName Property System.String AssemblyQualifiedName {get;} Attributes Property System.Reflection.TypeAttributes Attributes {get;} BaseType Property System.Type BaseType {get;} ContainsGenericParameters Property System.Boolean ContainsGenericParameters {get;} DeclaringMethod Property System.Reflection.MethodBase DeclaringMethod {get;} DeclaringType Property System.Type DeclaringType {get;} FullName Property System.String FullName {get;} GenericParameterAttributes Property System.Reflection.GenericParameterAttributes GenericParameterAttributes {g... GenericParameterPosition Property System.Int32 GenericParameterPosition {get;} GUID Property System.Guid GUID {get;} HasElementType Property System.Boolean HasElementType {get;} IsAbstract Property System.Boolean IsAbstract {get;} IsAnsiClass Property System.Boolean IsAnsiClass {get;} IsArray Property System.Boolean IsArray {get;} IsAutoClass Property System.Boolean IsAutoClass {get;} IsAutoLayout Property System.Boolean IsAutoLayout {get;} IsByRef Property System.Boolean IsByRef {get;} IsClass Property System.Boolean IsClass {get;} IsCOMObject Property System.Boolean IsCOMObject {get;} IsContextful Property System.Boolean IsContextful {get;} IsEnum Property System.Boolean IsEnum {get;} IsExplicitLayout Property System.Boolean IsExplicitLayout {get;} IsGenericParameter Property System.Boolean IsGenericParameter {get;} IsGenericType Property System.Boolean IsGenericType {get;} IsGenericTypeDefinition Property System.Boolean IsGenericTypeDefinition {get;} IsImport Property System.Boolean IsImport {get;} IsInterface Property System.Boolean IsInterface {get;} IsLayoutSequential Property System.Boolean IsLayoutSequential {get;} IsMarshalByRef Property System.Boolean IsMarshalByRef {get;} IsNested Property System.Boolean IsNested {get;} IsNestedAssembly Property System.Boolean IsNestedAssembly {get;} IsNestedFamANDAssem Property System.Boolean IsNestedFamANDAssem {get;} IsNestedFamily Property System.Boolean IsNestedFamily {get;} IsNestedFamORAssem Property System.Boolean IsNestedFamORAssem {get;} IsNestedPrivate Property System.Boolean IsNestedPrivate {get;} IsNestedPublic Property System.Boolean IsNestedPublic {get;} IsNotPublic Property System.Boolean IsNotPublic {get;} IsPointer Property System.Boolean IsPointer {get;} IsPrimitive Property System.Boolean IsPrimitive {get;} IsPublic Property System.Boolean IsPublic {get;} IsSealed Property System.Boolean IsSealed {get;} IsSerializable Property System.Boolean IsSerializable {get;} IsSpecialName Property System.Boolean IsSpecialName {get;} IsUnicodeClass Property System.Boolean IsUnicodeClass {get;} IsValueType Property System.Boolean IsValueType {get;} IsVisible Property System.Boolean IsVisible {get;} MemberType Property System.Reflection.MemberTypes MemberType {get;} MetadataToken Property System.Int32 MetadataToken {get;} Module Property System.Reflection.Module Module {get;} Name Property System.String Name {get;} Namespace Property System.String Namespace {get;} ReflectedType Property System.Type ReflectedType {get;} StructLayoutAttribute Property System.Runtime.InteropServices.StructLayoutAttribute StructLayoutAttribute... TypeHandle Property System.RuntimeTypeHandle TypeHandle {get;} TypeInitializer Property System.Reflection.ConstructorInfo TypeInitializer {get;} UnderlyingSystemType Property System.Type UnderlyingSystemType {get;}

As you can see, the System.INT32 class has a number of methods and properties. A method is something you can invoke to do something on the object, for example ToString() produces a string representing the value of the system.int32. A property is some attribute of the type, for example Name which is the name of the object. Within .NET there are two types of methods: static and object. Object methods are methods that you can invoke on a particular occurrence of a type. The ToString() method, for example, converts a specific System.Int32 to a string while TryParse() takes a value and sees if it will fit inside a 32-bit integer vaue. Static methods are methods that the class provides but that are not tied to a specific instance of a class. Classes can also have static fields, or values you can use in a PowerShellscript. In the case of system.int32, there are two static fields MaxValue and MinValue.

Here is a look at the TryParse static method, the ToString object method, plus the two static fields.

PS C:\Users\tfl> $ok=1 PS C:\Users\tfl> [system.int32]::tryparse("12345",[ref] $ok) True PS C:\Users\tfl> [system.int32]::tryparse("1234567890123",[ref] $ok) False PS C:\Users\tfl> (23456).tostring() 23456 PS C:\Users\tfl> [system.int32]::maxvalue 2147483647 PS C:\Users\tfl> [system.int32]::minvalue -2147483648

To see the static methods, object methods and object properties, you can use Get-Member or for fuller information, see the MSDN Library documentation on-line. To find this imploration simply, just Google for the type name (enclosed in square brackets) – this should show a link to the class definition as the first result, from which you can drill down to see more details about the class.

Technorati Tags: ,

Monday, January 22, 2007

Visual Studio "Orcas" - January 2007 CTP Ships

Microsoft has released a new beta of the next revision of Visual Studio. Code-named Orcas, this release is a Community Technology Preview (CTP). A CTP is an updated beta release of a product, which aims to provide uses with more timely access to new and updated features, at the possible expense of the very long testing time required for major beta releases. Microsoft first used this approach with the SQL Server 2005 and Visual Studio 2005 products (quite successfully IMHO!).

The interesting thing about this CTP is that MS are shipping it both as a normal product install (up to 4.3GB in total) and as a VPC Virtual Image. The VPC setup involves downloading 8 RAR files taking up 4.83 GB. Once these files are downloaded, you can extract the VHD image and create your VM - which means you need over 20GB of free space (for the download, for the temp file WinRAR creates, and for the actual VHD). Once the downloads are finished, I'll post another article with the actual size of the VHD.

The highlights of this CTP include:

  • Extended, more powerful data APIs with the ADO.NET Entity Framework and LINQ to ADO.NET
  • ADO.NET is fully integrated with LINQ
  • C# 3.0 Language Support
  • ClickOnce improvements
  • Managed classes for Elliptic Curve Diffie Hellman and Elliptic Curve Digital Signature Algorithm cryptographic functionality
  • Runtime and design-time support for Office 2007 (including Outlook 2007
  • Support for advanced lifetime management of add-ins and their AppDomains
  • Client service support for Login/Logout, Role management and Profiles
  • A trace listener that logs event to ETW, event tracing for Windows in Vista
  • Jscript Intellisense support
  • A new numeric type that provides support for very large numbers (i.e. beyond the range of In64)
  • LINQ over XML (XLinq)
  • SQL Server Compact Edition (SSCE) (SSCE provides a local relational data store for occasionally connected client applications from desktops to devices).

Monday, December 25, 2006

Smilla .NET Communications Library

This is a pretty cool .NET Communications Library doing neat stuff with NNTP.

See here for a tutorial on Smilla

Friday, December 15, 2006

Simplifying Deployment Using PowerShell

One of the things that I have really enjoyed, as a PowerShell MVP, is the sheer creativity of the community. It never ceases to amaze me how creative folks can be when given such a fantastic tool!

I got some mail this morning that pointed to a page on The Code Project, a Visual Studio and .NET community site. The page is entitled Deployment made simple using PowerShell. You can download a huge PowerShell script which handles some of your deployment needs. The script uses the .NET System.IO and System.Net class libraries.

Cool Stuff - well done Omar Al Zabir.

Saturday, November 05, 2005

Monad Beta 2 on .NET Framework 2.0 RTM

Microsoft has now begun shipping .NET Framework 2.0 (and Visual Studio 2005), even though the formal launch is not till Monday Nov 7th. If you want to run the RTM version of the .NET Framework (e.g. to run Visual Studio 2005 RTM) and you want the latest version of Monad, you'll need an updated version of the latter which you can download from here (for X86). If you are using X64, you can get the X64 Monad drop here.

This drop of Monad is the nearly the same as released earlier (but targetted towards an earlier version of the CLR). The only change is that the "Restricted" ExecutionPolicy is the default, which is discussed in the release notes.

Saturday, February 05, 2005

Get Ready for February Microsoft Patches

The relentless battle against bugs continues, and this month, there are a number of patches being distributed. These include the following

  • 9 Microsoft Security Bulletins affecting Microsoft Windows. At least one of these is Critical and some of these updates require a restart.
  • 1 Microsoft Security Bulletin affecting Microsoft SharePoint Services and Office. This is moderate and may require a restart.
  • 1 Microsoft Security Bulletin affecting Microsoft .NET Framework. Rated as important, the update requires a restart.
  • 1 Microsoft Security Bulletin affecting Microsoft Office and Visual Studio. Rated Critical, this update requires a restart.
  • 1 Microsoft Security Bulletin affecting Microsoft Windows, Windows
  • Media Player, and MSN Messenger. This is rated as Critical and requires a restart.
WHEW! Start planning now! And thanks to Susan Bradley. MVP Extroriainre, for the heads up on these.

Monday, September 13, 2004

Visual Studio 2005 Standard Edition announced

Today in Orlando, Microsoft announced a new edition of Visual studio, Visual Studio 2005 Standard Edition. This new edition was designed specifically for the needs of Visual Basic 6.0 and Web developers and contains much of the simplicity of the Express products that were announced at TechEd Europe. Standard Edition therefore becomes the entry point for professional development on the .NET Framework. Hopefully, we'll see the betas of this before long.