July 22nd, 2011

Learn About Two CodePlex Projects: PS2EXE and RoboPowerCopy

Doctor Scripto
Scripter

Summary: Get the inside scoop on two awesome CodePlex projects: PS2EXE and RoboPowerCopy.   Microsoft Scripting Guy Ed Wilson here. Today, we have a debut guest blogger. With us is Ingo Karstein to tell us about two of his CodePlex projects. Take it away, Ingo.   This is Ingo Karstein writing for this famous blog today. Thanks to Ed for the invitation.  I’m a senior consultant for SharePoint, Windows PowerShell, and custom development. I have been writing a blog where I discuss problems, ideas, and solutions related to these topics for about a year. Plenty of times, I am faced with problems that can be solved by software tools that I develop on my own. Years ago, I created in C# the tools that I needed for my job. I wrote the source code on a development machine with sample data in a lab environment. After that, I did some debugging and bug fixing. Finally, I used the compiled code in a live environment, hoping the program would do it right. These times are gone. There is Windows PowerShell in the world, and it was a kind of enlightening for me to get familiar with it. No longer do I need to do weird batch scripting or VBScript. In the last few weeks I developed two Windows PowerShell scripts: RoboPowerCopy and PS2EXE. You can download both projects at CodePlex, and you are more than welcome to participate in the future development of both projects.   Background on the tools RoboPowerCopy is an attempt to clone Robocopy in pure Windows PowerShell so that it runs on every machine without any prerequisites other than Windows PowerShell 2.0. Because of some limitations, it would be really hard or even impossible to cover the whole functionality of Robocopy with Windows PowerShell without having C# on board. But I didn’t want to have assemblies that have to be shipped with the RoboPowerCopy script. Windows PowerShell provides a middle course. It’s possible to embed C# in the script. This C# code is compiled at runtime and is immediately available in the script. Here is just a sample of using embedded C# code inside a Windows PowerShell script:

Add-Type -TypeDefinition @”

            public static class Message {

                        public static string GiveItToMe() {

            return “Hello World!”

}

            }

“@

 

[Message]::GiveItToMe()   This will show the simple message, “Hello World!” This ability to embed C# code in a Windows PowerShell script is the foundation for both RoboPowerCopy and PS2EXE. Both tools are plain Windows PowerShell scripts with inline C# code compiled dynamically at runtime using the Add-Type cmdlet. So far, so good. Let me talk about both tools.   RoboPowerCopy The idea of RoboPowerCopy was born out of my need to have more features in Robocopy, which is for me the best file copy tool in the Windows world. One missing functionality is “Verify,” a function that determines if the data written to the hard disk is identical to the source data, which ensures that the written data is correctly stored on the hard disk. In a first instance, I thought about cloning the Robocopy tool in C#, but I was afraid of deploying such a tool to a live system such as a SharePoint farm without a debugging infrastructure on the server. Malfunctioning could be a possible scenario. This was the reason why I didn’t do this project. I never would have run a self-made C# clone of Robocopy on a live system. But with Windows PowerShell as runtime for the too, l this became possible: on every Windows 2008 R2 server, Windows PowerShell is already installed, and the Windows PowerShell ISE (Integrated Scripting Environment) can be installed as a Windows feature. No administrator would have reservations about that. It’s not third party; it’s from Microsoft and it’s a part of the operating system. Debugging and bug-fixing a Windows PowerShell script on a live system’s server is possible. Here we go! The only problem is the inline C# code, which is not debuggable in Windows PowerShell ISE. This code needs to be created in a common way, but it is not compiled to an assembly. It remains source code, plain text inside the Windows PowerShell script. It can be changed and will be recompiled during the next run of the script. After changing the C# code, you need to restart Windows PowerShell ISE, because the dynamically created assembly is loaded into the AppDomain and cannot be changed there. This is a limitation of the .NET Framework. RoboPowerCopy uses some C# classes:

  • For long-path support: reading and writing files and directories with full names longer than 256 characters. Win32 API functions support paths up to 32,000 characters. But this is not supported by the .NET Framework, and because of that, it is not supported by Windows PowerShell.

 I’ve created classes:

  • LongPathSupport: Some common functions and wrappers of Win32 API calls.
  • LongFileInfo: Similar to System.IO.FileInfo, but supporting long paths.
  • LongDirectoryInfo: Similar to System.IO.DirectoryInfo.

 

  • For getting and setting time stamps of files with long paths.
  • For getting and setting attributes of files or directories with long paths.
  • For getting and setting security information.
  • At least a class for the copy header that is added to each file during the copy process. This header contains information about the copy process and enables the script to restart the copy process at the file position where the copy process was stopped at the last attempt.

All other parts of RoboPowerCopy are plain Windows PowerShell:

  • Reading command-line parameter in batch style (with slash) to have a Robocopy compatible set of parameters.
  • Scanning source and destination paths.
  • Copy files.
  • Delete files.
  • Fix security and time stamps.

The RoboPowerCopy script is not finished at the moment. It’s still an alpha. It needs some improvements, such as copy folder security, set compressed file attribute, set encrypted file attribute, and add multithreading. I’d like to invite you to help to improve RoboPowerCopy. Just send me email via the project’s CodePlex page.   PS2EXE The second tool I’d like to introduce is the PS2EXE script. The name means: “PowerShell to EXE.” On CodePlex I use this short description for the script: “Convert Windows PowerShell scripts to stand-alone EXE files.” But this description is not entirely correct. On one hand, it’s slightly incorrect because the PS2EXE tool is not a “converter.” It does not translate a Windows PowerShell script into another language. It just embeds the Windows PowerShell script in a C# program that compiles to an EXE file. On the other hand, the description is not correct because it implies that the resulting EXE would be “stand-alone”. The EXE will always need the Windows PowerShell 2.0 execution environment to take place. Let me explain this more in detail: 1. The “powershell.exe” is part of the Windows PowerShell environment. It’s the command-line version of Windows PowerShell. But this program is not Windows PowerShell per se; it is not the Windows PowerShell framework itself! PowerShell.exe is just a so-called “Windows PowerShell host.” Such a host is a kind of interface between the world outside the Windows PowerShell environment and the Windows PowerShell framework. “Powershell.exe” is a command-line based interface between a user and Windows PowerShell. “Powershell_ise.exe” is a GUI-based Windows PowerShell host with debugging functionality. Windows PowerShell itself is a set of .NET Framework classes that can be used like other .NET Framework classes (to develop a new Windows PowerShell host or just to execute a Windows PowerShell script inside a .NET Framework program). So I’ve created a simple command-line based Windows PowerShell host that is able to interact with the user. This host creates a Windows PowerShell runtime environment (“Runspace”) and executes a Windows PowerShell script that is stored in a string variable inside the program. 2. I’ve created the “PS2EXE.ps1” as a Windows PowerShell script. This script has some inline C#. But other than in RoboPowerCopy, this C# code is not compiled into the memory and is not used immediately in the script. Instead, the C# code compiles into an EXE using the CSharp compiler utilized by the PS2EXE script. Before compiling the C# code, the PS2EXE.ps1 script manipulates the inline C# source code and inserts the base64 encoded source code of the other Windows PowerShell script that the user wants to convert to EXE. It just injects the script into the C# source code and then compiles the C# code into an EXE. 3. The resulting EXE still needs the Windows PowerShell environment to execute. It’s not a stand-alone application. It will not execute on a machine that does not have Windows PowerShell installed. And it will not run if script execution is prohibited. But that’s more than okay for me!   Advice for creating inline C# Because it’s not possible to debug the inline C# code, you should create a “real” project in Visual Studio just to develop and bug-fix the C# code. Usually, I create a Console Application project in which the Main method calls all the code that will be embedded in Windows PowerShell later. The Main method acts as a replacement for the calls that will be done later in Windows PowerShell. This is the way I’ve gone with the inline C# code of RoboPowerCopy and with the specially implemented Windows PowerShell host of PS2EXE. The C# code inside could not be developed without a full-featured development environment. I’d be happy to get your feedback and comments about this article and the tools RoboPowerCopy and PS2EXE. Please leave a comment below, on my blog, or on CodePlex.   Thank you, Ingo, for sharing some insights into your two CodePlex projects. I enjoyed reading the blog post. I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace. Ed Wilson, Microsoft Scripting Guy

 

Author

The "Scripting Guys" is a historical title passed from scripter to scripter. The current revision has morphed into our good friend Doctor Scripto who has been with us since the very beginning.

0 comments

Discussion are closed.