ScorpioTek Solutions
07-filler-left Information about ScorpioTek Services Offered by ScorpioTek Training Courses Offered by ScorpioTek Technology Blog by ScorpioTek Contact us for more information on training/services 08-filler-right
06-message

Archive for the ‘C#’ Category

How to solve: The type or namespace name ‘Session’ does not exist in the namespace ‘Microsoft.Hpc.Scheduler’

Saturday, May 21st, 2011

If you attended one of the developer labs and are trying to create your SOA client (or use one of the already built solutions) and you are using the SDK from HPC Server 2008 R2 SP2 Beta, then you might see the following error:

The type or namespace name ‘Session’ does not exist in the namespace ‘Microsoft.Hpc.Scheduler’

This had me stomped for a while. For some reason, the default profile for C# apps in VS2010 SP1 is .Net Framework 4 Client Profile:

This profile is limited to seeing only the following references:

Which means that even if you add the Microsoft.Hpc.Scheduler.Session reference, it will not be able to use it.

The fix is easy, all you need to do is change the profile of your client to .Net Framework 4.0

You will then be able to see the references from the Add Reference dialog and everything will compile fine:


How to Execute Remote PowerShell Commands using C#

Sunday, April 11th, 2010

UPDATE: The post below works when you are trying to execute simple commands.  I had issues when trying to execute full scripts.  After searching some more, I found amazing tutorials on how to carry out this procedure, check them out:


Before I start this post that I am urging to write (before I forget all I did), I must clarify that all the code here was from various sites/forums.  All I did was to try and get the combination right, which basically took all of my time yesterday.  Nonetheless, at least it’s working.

So what I am writing at this moment is a C# application that will issue SCVMM commands from any machine in my domain.  SCVMM’s API is 100% PowerShell, so anything you need to run automatically via code in SCVMM, needs to be called through PowerShell somehow.

PowerShell v2.0 includes Remoting, which allows you to issue PowerShell commands remotely on other machines by using Windows Remote Management (WinRM).  So let’s see how on Earth this is done:

Pre-reqs

Before you do any of this, you must run the following command in an admin PowerShell command prompt on the machine where you would like to run the remote command:

winrm quickconfig

The Code References

You need to use the correct version of System.Management.Automation.dll.  If you are running Windows 7 / Windows Server 2008 R2, you must include this reference in your project from the following path:

C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll

Note: When importing the aforementioned DLL, I was having all kinds of issues with Visual Studio 2008.  I tried it with Visual Studio 2010 and it worked right away.

The Namespaces

Include the following namespaces in your code:

using System.Management.Automation; // Windows PowerShell namespace
using System.Management.Automation.Runspaces; // Windows PowerShell namespace
using System.Security; // For the secure password

The Function

This is the function you need to invoke when you want to run a remote command.  The incoming string, scriptText, is the PowerShell command you would like to execute:

public static string RunScript(string scriptText)
        {

           Runspace remoteRunspace = null;
           openRunspace("http://SERVERNAME:5985/wsman",
                "http://schemas.microsoft.com/powershell/Microsoft.PowerShell",
                @"DOMAIN\USERNAME",
                "PASSWORD",
                ref remoteRunspace);

                StringBuilder stringBuilder = new StringBuilder();
                using (PowerShell powershell = PowerShell.Create())
                {
                    powershell.Runspace = remoteRunspace;
                    powershell.AddCommand("get-process");
                    powershell.Invoke();
                    Collection<PSObject> results = powershell.Invoke();
                    remoteRunspace.Close();
                    foreach (PSObject obj in results)
                    {
                        stringBuilder.AppendLine(obj.ToString());
                    }
                }

                return stringBuilder.ToString();
         }

Note that you must replace DOMAIN\USERNAME with your domain and username.  You must also replace PASSWORD with your password.  I really don’t know how to carry this out using my logged-in credentials, so until then, I’ll have to include my password in the code, which is crappy but works.  Also note that you must also replace SERVERNAME with the machine you are trying to connect to.  The port MUST be 5985, if you try the default (80), it will fail to connect (at least, it did in my case).

The magic happens inside the static function openRunspace which is defined as follows:

        public static void  openRunspace(string uri, string schema, string username, string livePass, ref Runspace remoteRunspace)
        {
            System.Security.SecureString password = new System.Security.SecureString();
            foreach (char c in livePass.ToCharArray())
            {
                password.AppendChar(c);
            }
            PSCredential psc = new PSCredential(username, password);
            WSManConnectionInfo rri = new WSManConnectionInfo(new Uri(uri), schema, psc);
            rri.AuthenticationMechanism = AuthenticationMechanism.Kerberos;
            rri.ProxyAuthentication = AuthenticationMechanism.Negotiate;
            remoteRunspace = RunspaceFactory.CreateRunspace(rri);
            remoteRunspace.Open();
        }

Let me know if it works for you in the comments.

Sources:

How to Increase the MaxArrayLength in a WCF Component

Friday, January 2nd, 2009

I was doing some benchmarking for a client to see if Interop calls from a WCF service would hinder performance and defy the whole purpose. I was using variable byte arrays to send data to build a performance graph of data vs. time.

My efforts were quickly shut down by the fact that by default (to avoid exploits) WCF cannot receive data in an array from a client whose length is bigger than 16K:

“The formatter threw an exception while trying to deserialize the message: Error in deserializing body of request message for operation ‘XXX’. The maximum array length quota (16384) has been exceeded while reading XML data. This quota may be increased by changing the MaxArrayLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader. Line 1, position 39987.”

Like the message says, you can change these values in the client’s app.config file, but that is not taking you anywhere. There are various scenarios for this issue:

  • WCF Component Hosted in IIS
  • Self Hosted WCF Component

To allow bigger arrays, you need to change 2 config files:

  • The client’s app.config
  • The Server’s config file

Let’s start with the client’s config file:

Find the readerQuotas element and change the values of the following attributes to 2147483647: maxDepth, maxStringContentLength, maxArrayLength, maxBytesPerRead, maxNameTableCharCount (this may be overkill as probably maxArrayLength does the trick, but I did not want to take any chances):

   1: <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
   2:  maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />

In order to fix the server’s config file, you need to edit the web.config file if the service hosted on IIS *OR* the app.config file of the self hosted web service. First, you want to make sure that you define a a new binding:

   1: <configuration>
   2:   <system.serviceModel>
   3:     <bindings>
   4:       <basicHttpBinding>
   5:         <binding name="myBindingForBigArrays"
   6:             maxReceivedMessageSize="2147483647">
   7:           <readerQuotas
   8:               maxDepth="64"
   9:               maxStringContentLength="2147483647"
  10:               maxArrayLength="2147483647"
  11:               maxBytesPerRead="4096"
  12:               maxNameTableCharCount="16384"/>
  13:         </binding>
  14:       </basicHttpBinding>
  15:     </bindings>


Once you have defined this binding, you need to add it to your services endpoint definitions (line 3)

   1: <services>
   2:   <service behaviorConfiguration="NewBehavior" name="XXX">
   3:     <endpoint bindingConfiguration="myBindingForBigArrays" address="basic" binding="basicHttpBinding"

Windows LiveWriter rocks!

Source:

http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/75065538-eed4-48cd-8252-1ff3e795bcfb

Do as I Say, Don’t Do as I Do

Tuesday, November 25th, 2008

Today I really wanted to kick myself for trying to get around a problem when trying to make a C# console application instantiate a COM DLL. I had created these 2 projects under the same solution, but when I was debugging, a COM exception exploded in my face:

201002251603.jpg
System.Runtime.InteropServices.COMException was unhandledMessage=”Retrieving the COM class factory for component with CLSID {20156CB7-8B2F-4B55-9F79-0DE4E8E04145} failed due to the following error: 80040154.”

I was baffled as the COM component was registered successfully.

After looking for CLSIDs in the registry, and toying around with the OLE COM Object Viewer, it struck me.

I had created the C# and COM projects under the same solution. C++ projects on Visual Studio are created to target x86 by default whereas managed projects are created to target AnyCPU by default.

Since I was running this on a 64-bit OS, the C# app ran as a 64-bit process and was looking under the 64-bit registry section to find info on the InprocServer, which had been registered as a 32-bit component.

I changed the C# application to target 32-bit, and the COM error was gone.

I can only help but feel foolish for stumbling onto this mistake. I think I spent about 2 years training people on how to avoid these pitfalls, and yet, here I was in too deep…tsk tsk.

On to the next thing…

How to Clear a DataGridView Table in C#

Sunday, September 21st, 2008

Had me baffled for a while:

int rowCount = DataGridView1.RowCount – 1;

for (int i = 0; i < rowCount; i++)

{

DataGridView1.Rows.Remove(DataGridView1.CurrentRow);

}

Windows Communication Foundation Lab Revisions

Monday, June 9th, 2008
skitchELXOWZ

Ever since I started working a bit more on Windows HPC Server 2008, I knew that I had to learn the basics of WCF (Windows Communication Foundation) and pronto. I was lucky I had bought a great book a while back that was currently stacked alongside a minion of books waiting to be read. The book is called “Learning WCF” by the good fellows at O’Reilly. This has been an amazing source of information as of now.

I also found some great .Net Framework 3.0 labs (virtual) from the following site:

http://msdn.microsoft.com/en-us/virtuallabs/aa740389.aspx

The labs are a great place to start since you have to suffer creating everything from scratch, which in my experience is the best way to learn. I am not buying the whole virtual lab thing yet though, reasons include: not being able to save your session or extend the time, network lag, very small window to work with, etc. So I downloaded the PDF from the lab (MSDN Virtual Lab: The Fundamentals of Programming the Windows Communication Foundation) and tried it on my VM running Visual Studio 2008.

The bad thing is that the labs are a bit outdated, so even though they will work on the virtual lab environment, you will be using deprecated methods, attributes, and so on, which is not good at all. Running the labs in VS2008 had a bunch of issues that took a while to track down and fix. In case you want to carry out the lab with Visual Studio, I have posted the PDF I used that contains some notes on what you need to change to make things work. The lab is definitely worth carrying out if you want to learn the basics of WCF:

http://www.yousendit.com/transfer.php?action=batch_download&batch_id=RXNqQ1ZyTERFc0kwTVE9PQ

Now, it is time to understand and work with the WCF Broker Nodes in Windows HPC Server 2008 :)

How to Invoke a Method from an Object Returned in a WMI Query

Thursday, April 10th, 2008

The more I use WMI, the more I like it. I thought WMI was just a way to obtain info and nothing more; but lately I have found that it is an extremely powerful that offers much much more.

I was writing an assembly to carry out an operation with Windows Hyper-V (whatever that operation was is not relevant to the post). Anyhow, I got a list of objects from the query, it looked something like this:

ManagementObjectSearcher searcher =

new ManagementObjectSearcher(“root\\…”,

“SELECT * FROM ….”);

From there, you can loop through every element in the collection and obtain any property that it has:

foreach (ManagementObject queryObj in searcher.Get())

{

//Do something with queryObj["some property"]

}

But what if the object contains a method? How would you call it? You just need to use the InvokeMethod function of the ManagementObject instance and you are good to go:

foreach (ManagementObject queryObj in searcher.Get())

{

queryObj.InvokeMethod(“Method Name Here”, new object[] {32769});

}

If you want more info on all of this, check this article.