Category Archives: .NET

PowerShell: Getting Started with Win32 API


Blog on Request!

Someone asked me to delve in to Win32 API use in PowerShell. Personally I don’t feel that I’m the best person to explain this, but I’ve done it a few times now so I think I have a decent handle on it.

Let me just start off by saying Win32 API should be your last choice (ok, second to last, I hate COM). You should do a very through search of the .NET framework before jumping in to the Win32 API pool.

Once you’ve exhausted all other options and have ended up in the Win32 world, what do you do? I’m not going to go over how to find the right WIN32 API for the task because if you are at this point, you’ve probably already found the API and just want to know how to use it.

First off load up the MSDN doc for it and the PInvoke.net doc. Usually googling the API will land you on those two pages pretty quickly.

Now for an example lets take a look at an API I’ve recently been playing with, GetSystemFileCache (pinvoke)

The Signature that MSDN gives us looks like this.

BOOL WINAPI GetSystemFileCacheSize(   __out  PSIZE_T lpMinimumFileCacheSize,   __out  PSIZE_T lpMaximumFileCacheSize,   __out  PDWORD lpFlags );

Which is the signature you’d use if you were coding in C++.  Since there is no direct way to use this in PowerShell we’re going to embed this in C# code and then consume that code in PowerShell. In many cases I’ll write the C# console app first and then apply that to my PowerShell script. This is what I did with my NetStat script, which was fairly complex. In this case we’re just calling a simple method to pull the current Cache limits.

Lets take a look at this Signature. The first thing shown is BOOL, which is the return type which the docs show is any nonzero number for success. Easy enough. bool is the same in C++ as it is in C#.

Next is WINAPI which is just a tag to show its a win32 api, this can just be removed.

After this is our method name, GetSystemFileCacheSize, easy enough.

Now this is where it gets a little tricky because we often times need to convert C++ types to something C# knows.

We see we have 3 arguments here, all 3 of which are prefixed with __out, which means they are output variables (If you don’t know how to program that well it’s basically passing a reference to a variable to return multiple things). So anytime you see __out, that means the variable needs to be passed in as a reference. We’ll get to that in a moment. Next is the type that the variable needs to be. Two of which are whats called PSIZE_T and one is a PDWORD. In both cases these are prefixed with a P, which indicates Pointer (pointer, reference, __out – all the same thing) so really the type is SIZE_T and DWORD.

How do we know what SIZE_T and DWORD are in C#? Google is really your best option here, or hopefully PInvoke.net has a signature you can use. In this case PInvoke does have it, but lets pretend it doesn’t. When we google ‘C# dword’ we get some good results that let us know this is an unsigned Int (UInt32). Another clue we have is that in the MSDN docs it tells us that it’s a flag and it can have a value of 0x1 or 0x4, both of which fit in to an int just fine. So, which do we use? It doesn’t matter, provided all possible return types can fit in.

Next is that Size_T, again googling ‘C# SIZE_T’ gives us some good info as does PInvoke, but lets just google SIZE_T.

Doing so provides a great data type reference.

We can see that PSIZE_T is in there but it just says it’s a pointer to SIZE_T which we already knew.

“The maximum number of bytes to which a pointer can point. Use for a count that must span the full range of a pointer.

This type is declared in BaseTsd.h as follows:

typedef ULONG_PTR SIZE_T;

So this says it’s a ULONG (unsigned long, a long in C# is Int64, which google will help with again) It also indicates that it’s a pointer. This is where PInoke really saves us. It lets us know about an IntPtr type that is a special pointer specifically for this.

So now our new C# signature is as follows

bool GetSystemFileCacheSize(ref IntPtr lpMinimumFileCacheSize, ref IntPtr lpMaximumFileCacheSize, ref int lpFlags);

We see that it specifies ref for all the __out variables (in this case all of them, but some times they are __in) and a data type of IntPtr and int.

We’re still in the C# side of the world. we’ll need to use the System.Runtime.InteropServices (otherwise known as pinvoke). If you don’t know C# this might be a bit tricky, but we’re going to write a small C# class to contain our method and create a wrapper function around it. Not always needed but I find it makes it easier to work with.


using System;

using System.Runtime.InteropServices;

public class test1

{

[DllImport("kernel32.dll")]

public static extern bool GetSystemFileCacheSize(ref IntPtr lpMinimumFileCacheSize, ref IntPtr lpMaximumFileCacheSize, ref int lpFlags);

public struct CacheSize

{

public Int64 Min;

public Int64 Max;

public int Flags;

}

public static CacheSize GetSize()

{

IntPtr lpMin = IntPtr.Zero;

IntPtr lpMax = IntPtr.Zero;

int lpFlags = 0;

bool b = GetSystemFileCacheSize(ref lpMin, ref lpMax, ref lpFlags);

CacheSize size = new CacheSize();

size.Min = lpMin.ToInt64();

size.Max = lpMax.ToInt64();

size.Flags = lpFlags;

return size;

}

The first part of this is just adding the pinvoke namespace and the basic system namespace which helps with the IntPtr. We then create a public class. I usually start with Test1 because once you add a type to PowerShell you can’t overwrite it.

Then you’ll see the keywords [DLLImport("kernel32.dll")] so depending on what DLL your function is in will determin what you put in there which is followed by the signature.

Next I created a struct to help with the output to PowerShell. You’ll see how this comes in to play as we start to work with the PowerShell side of things. For now just see that it’s a simple holder for our return data. Next is our function wrapper. I’ve called it GetSize which returns my struct. You’ll also notice that it’s prefiexed with public static for both, which is important for accessing it within PowerShell.

In my function I set my min and max pointer to zero (special pointer zero) and the flags to zero. I then call the win32 api passing it the variables I created as references (pointers) and capture the return in b which if I was trying to do something for production, I’d check the return value.

I then create an object of my type CacheSize and populate it with the return values and return that to the caller.

Now that the C# is done, how do we apply this in PowerShell?

If you read my blog you’ll notice I’ve used Add-Type a few times which is a great tool for adding in types or C# code as we are doing here so we’ll just wrap this in a here-string and pass it to Add-Type like so:


Add-Type

<span style="color: #8b0000; font-family: Lucida Console; font-size: xx-small;"><span style="color: #8b0000; font-family: Lucida Console; font-size: xx-small;"><span style="color: #8b0000; font-family: Lucida Console; font-size: xx-small;">@'</span></span></span>

using System;

using System.Runtime.InteropServices;

public class test1

{

[DllImport("kernel32.dll")]

public static extern bool GetSystemFileCacheSize(ref IntPtr lpMinimumFileCacheSize, ref IntPtr lpMaximumFileCacheSize, ref int lpFlags);

public struct CacheSize

{

public Int64 Min;

public Int64 Max;

public int Flags;

}

public static CacheSize GetSize()

{

IntPtr lpMin = IntPtr.Zero;

IntPtr lpMax = IntPtr.Zero;

int lpFlags = 0;

bool b = GetSystemFileCacheSize(ref lpMin, ref lpMax, ref lpFlags);

CacheSize size = new CacheSize();

size.Min = lpMin.ToInt64();

size.Max = lpMax.ToInt64();

size.Flags = lpFlags;

return size;

}

}

'@

NOTE: Be careful of new lines in this code, the code formatter has been doing weird things to me lately.

Once you run that its imported the class in to our running environment and we can access that method like so.


$rtn = [test1]::getsize()

$rtn

$rtn | select @{n='min';e={$_.min /1mb}}, @{n='Max';e={$_.max/1gb}},flags

The return should be the same on all systems (at least what I’ve seen from tests) as 1MB min and 1024GB max. If you have a file server that’s hosting TB’s of data, you might find this to be a problem when its eaten all of your memory in system cache!

There is a way to set it with a win32 API that im working on now. I’ll be sure to post that solution when I figure it out!

I hope this has helped you understand how to use Win32 APIs a little better!

List OLE/ODBC Providers with .NET


Recently I wanted to be able to list the OLE/ODBC Providers installed on a system. Not horribly hard, but also didnt have a ton of luck finding info on how to do this.

OLE

For OLE there is a .NET library that allows you to do this fairly easily. I focused in on the wrong method at first but thanks to help from BigTeddy over at the Technet Powershell forums the problem was resolved.

System.Data.OleDBEnumerator class has a GetElements method that will return a list of available providers.


(New-Object system.data.oledb.oledbenumerator).GetElements()

ODBC

Oddly enough, you would think that the System.Data.ODBC namespace would have something along those lines, but no. If it does, I cant find it. However, you can pull it from the registry fairly easily from the following location.

HKLM:\Software\ODBC\ODBCINST.INI\ODBC Drivers


Get-ItemProperty 'HKLM:\SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers'

#32 bit drivers on a 64 bit system here

Get-ItemProperty 'HKLM:\SOFTWARE\Wow6432Node\ODBC\ODBCINST.INI\ODBC Drivers'

Validate NetBIOS Domain Name to see if its in use or just test to see if its valid. Powershell/C#


 

Recently someone in the forums asked how they could check to see if a NetBIOS Domain Name was in use or not. Come to find out there isn’t a .NET methods for doing this that I could find but there is an API function for that. First I’ll show the C# and then I’ll show how to use it in Powershell. Creating a C# console app was how I went about figuring this out for Powershell.

First I took a look at the API which looked pretty easy to bring in to C# and then I called it within my Main() function. Here is the complete C# console code.

using System;

using System.Runtime.InteropServices;

 

public class NetworkUtil

{

    [DllImport("Netapi32.dll",SetLastError=true,CharSet=CharSet.Unicode)]

    public static extern UInt32 NetValidateName(string lpServer,string lpName, string lpAccount,string lpPassword, int NameType);

 

    static void Main()

    {

        UInt32 rtn = NetValidateName(null, "jrich-pc", null, null, 1);

        Console.WriteLine(rtn);

        Console.ReadKey();

    }

}

So lets walk through this. First I only included (using) the System and InteropServices (PInvoke) and then created a class for this. I used NetworkUtil so that I could extend my class in my NetStat powershell cmdlet if I wanted (I suspect this will grow over time).

I then used the DLLImport to pull in the function from the .dll file. I’ve included the SetLastError simply because I saw it on most but its not really needed. The CharSet being set to Unicode is very important. That part threw me for a loop. The docs don’t really talk about it and the only reference is in their example. I stumbled across it when looking at another example of a similar call (www.pinvoke.net)

The question that should be running through your mind right about now is, how did you convert the C++ function signature to C#? The answer is simple, I guessed based on what it implied. The first time I started to play with PInvoke stuff I was surprised at how forgiving the types were. Granted this can get you in trouble, but if you know what you are expecting in return, you can go from there and tweak it.

The C++ signature is as follows.

NET_API_STATUS NetValidateName( __in LPCWSTR lpServer, __in LPCWSTR lpName, __in LPCWSTR lpAccount, __in LPCWSTR lpPassword, __in NETSETUP_NAME_TYPE NameType );

 

The return type is a structure of error codes that boil down to numbers, so I said hey, lets make it a INT32, I later found a negative error code so I changed it to UINT32, you almost never see negative numbers (I’ll look at that in a bit). Then we need to keep the name the same. For the param’s we’ll see most are LPCWSTR which is a string (docs tell you and the STR gives it away) so I simple made them all strings in the C# code. The last param is of type NETSETUP_NAME_TYPE which is defined in the docs to be a simple ENUM that is 0-5. At first I created the ENUM but then decided it was easy enough to just send it a number and if I needed to change it I’d reference the docs.

Then I get to testing this from my main function with a simple call.

UInt32 rtn = NetValidateName(null, "jrich-pc", null, null, 1);

Reading the docs you’ll see the inputs are pretty basic;

Server – The server to query again, null is the local machine, this should be fine for most.

Name – The name you want to query for

Username and Password – If you query a server (an AD server) you can provide creds, if you don’t it uses the current context (you)

Name Type – This is the type of query you want to preform.

The Name Type can be found on the docs page, but I’ve copied them here for simple reference. The two that seem to be of most value are 1 and 3.

Value

Meaning

NetSetupUnknown

0

The nametype is unknown. If this value is used, the NetValidateName function fails with ERROR_INVALID_PARAMETER.

NetSetupMachine

1

Verify that the NetBIOS computer name is valid and that it is not in use.

NetSetupWorkgroup

2

Verify that the workgroup name is valid.

NetSetupDomain

3

Verify that the domain name exists and that it is a domain.

NetSetupNonExistentDomain

4

Verify that the domain name is not in use.

NetSetupDnsMachine

5

Verify that the DNS computer name is valid.

This value is supported on Windows 2000 and later. The application must be compiled with _WIN32_WINNT >= 0x0500 to use this value.

 

These are pretty well documented and make good sense. As I said typically you’ll use 1 and 3 and maybe even 4 depending on how you want to code your app.

 

The part that was hardest was tracking down these error codes. I found the best way was to google the display names that the docs showed. Here is a table I made with the Error Codes I was able to track down.

NET_API_STATUS Error Codes

Number

Name

Meaning

50

ERROR_NOT_SUPPORTED

 

52

ERROR_DUP_NAME

It found what you were looking for

53

ERROR_BAD_NETPATH

It wasn’t able to connect to your query server

1210

ERROR_INVALID_COMPUTERNAME

 

1355

ERROR_NO_SUCH_DOMAIN

 

2351

NERR_InvalidComputer

 

2695

NERR_InvalidWorkgroupName

 

9556

DNS_ERROR_NON_RFC_NAME

 

9560

DNS_ERROR_INVALID_NAME_CHAR

 

2147549463

RPC_E_REMOTE_DISABLED

Found query server but RPC wasn’t available

 

Most of these codes are pretty obvious and should make sense once you start to test it.

 

Powershell!

Now, lets use this in powershell. Its actually pretty easy once we figure that part out.

Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;

public class NetworkUtil
{
    [DllImport("Netapi32.dll",CharSet=CharSet.Unicode)]
    public static extern UInt32 NetValidateName(string lpServer,string lpName,string lpAccount,string lpPassword,
        int NameType);
}
"@

Function Test-NetBIOSName{

param([string] $Name, [int] $NameType)
[NetworkUtil]::NetValidateName($null,$name,$null,$null,$NameType)
}

#TEST

Test-NetBIOSName “myserver” 1

The function I created is very basic. You could tweak the param’s to validate input and the such, but I’ll leave that up to you.

Hope this helps!

.NET 4.0 Chart Control Problem – Connection Was Not Closed


So, I’ve go this huge perfmon log file that I’m trying to get some charts out of and excel just isn’t cutting it for me and SSRS just turned out to be a pain and no easier than making my own app (learning curve) so here I am, making a basic charting program in C#. As you may have noticed I spend most of my time in Powershell so I’m stumbling over this a bit and I ran in to a problem using the charting control that is telling me the connection was not closed when I attempt to bind my SQLCommand object to the chart control. Come to find out the connection needs to be closed and the chart needs to open it.

here is some sample code:

         

          string query = "select field1, field2 from table";
          string connstr = "Server=yourserver;Database=yourdb;integrated security";
          SqlConnection conn = new SqlConnection(connstr);
          SqlCommand cmd = new SqlCommand(query, conn);
          
          try
          {
              chart1.DataSource = cmd;
              chart1.Series["Series1"].XValueMember = "field1";
              chart1.Series["Series1"].YValueMembers = "field2";
          }
          catch (Exception Ex)
          {
              MessageBox.Show(Ex.Message);
          }

 

 

As you’ll notice, no where do you open or close the connection, its handled by the chart. Seems a little weird to me, but I guess that’s cool.

Follow

Get every new post delivered to your Inbox.

Join 115 other followers