Skip to content

Visual Basic: The most excellent code editor

I can’t hide the fact that I have a childish love for Visual Basic. I think this is worth a few blog posts. Than language and the code editor together works so incredible well for me. The language provides code blocks with keywords for opening and closing, so that you can read out what kind of block is closing. Because of this, the code editor knows about your intentions. Also, the C# editor cannot know if you intend to use curly brackets or not, because they are optional if only one statement will be contained within a block. In C#, to do an iteration with a test in, the iteration and its brackets has to be typed out, and then the test and its brackets has to be typed out.

In Visual Basic, I just write the iteration opening, and when hitting Enter, the editor closes my iteration, does the indentation and places the cursor within, so that I can continue writing my test. Again, I just write the opening part of the test and hit Enter, and the editor closes it, does the indentation and place my cursor within the new block.

for (int a = 0; a <= 10; a++)
{
   if (true)
   {
      //Alcatraz style
   }
}

For A As Integer = 0 To 10
  If True Then
     'Quick and nice!
  End If
Next

Also, what } actually means, might depend. Yes, it is a closing block, but what block? In Visual Basic, the block closers are nice and readable. Next is closing For, End While is a closing While, End If is a closing If, and so on.

Categories: Visual Studio 10.

My bits on evolution, part 6

Some of my bits for the Swedish Skeptic Podcast, Skeptikerpodden, on evolution and creationism, in Swedish.

Några av mina bidrag till svenska Skeptikerpodden om evolution och kreationism, på svenska.

16. Kreationistpropaganda från Bibelfokus.se (del 3 av 3) (från Skeptikerpodden 18/1 2011)

17. Information och evolution (från Skeptikerpodden 8/2 2011)

18. Design och förklaringsvärde (från Skeptikerpodden 8/3 2011)

Föregående

Categories: Science.

Tags:

PowerShell knows about your USB devices

One of many things you can do with the Management assembly is to get the USB devices that is currently connected to your computer. To load the Management assembly, use this line of code (no line break here):

[System.Reflection.Assembly]::Load("System.Management, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")

The class you want to create an instance from is called ManagementClass, and to its constructor you pass the management path that you want to use. USB devices are located in the Win32_USBHub path, so that is the argument that I pass to the constructor.

$Man = New-Object System.Management.ManagementClass("Win32_USBHub")

The GetInstances function returns a collection of objects, each object representing a device that actually is connected. Just for being crazy, I will make my target variable type safe.

[System.Management.ManagementObjectCollection]$Devs = $Man.GetInstances()

Now I can use ForEach-Obect cmdlet to iterate through the collection. For each device, I will write out the name of the device, the system ID and a blank line.

$Devs | ForEach-Object {
	Write-Output $_.GetPropertyValue("Name").ToString()
	Write-Output $_.GetPropertyValue("DeviceID").ToString()
	Write-Output ""
}

Finally, I have to free the resouces I have used.

$Devs.Dispose()
$Man.Dispose()

When you run this code, you should see a list of devices that is registered as connected to your machine, including the USB hubs. If you connect a device and run the script again, that device will show up in the list. With this code as base, you could easily write programs that detects changes to the list. That is, programs that detects when a new device is added or removed. The last item should be the device you inserted while your computer was running, and the first items are the devices that were available at system startup.

Categories: PowerShell.

Tags:

Adding references to custom types

In a great number of blog posts, I have used the Load function of System.Reflection.Assembly to load types from the .NET Framework. This (without line break) is an example that gives you access to the Forms library…

[System.Reflection.Assembly]::Load("System.Windows.Forms, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089")

…so that calls like this is possible:

[System.Windows.Forms.MessageBox]::Show("Hello!")

(To see the available assemblies, check the assembly folder in your Windows folder.)

When you use the Add-Type cmdlet to create your own types, the string that describes the type might need references as well. The required assemblies are specified in an array, and passed to the cmdlet as the -ReferencedAssemblies argument. This code adds a custom type…

$references = @("System.Windows.Forms")
Add-Type -ReferencedAssemblies $references @'
public class Test
{
   public void hej()
   {
      System.Windows.Forms.MessageBox.Show("Hello!");
   }
}
'@

…gives you a code that when invoked, does the same thing:

$test = New-Object Test
$test.hej()

The problem will show up if you have made any changes to your type and run your program again. The type called Test will already be loaded, so the Add-Type cmdlet will fail.

(If you run your program again, without changing your custom type definition, Add-Type will just be ignored – your type is there and everything is fine.)

Since types cannot be unloaded, you will need to unload your entire appdomain, and the easiest way to do this, is to close your PowerShell window. So any changes to a custom type, will be reflected in a new instance of PowerShell, thus in a new appdomain.

Categories: PowerShell.

Environment variables

Assuming that you are running Windows 7, the environment variables can be manually accessed if you right click on Computer, and select Properties. From there, you click Advanced system settings and on the Advanced tab, you click the Environment variables button. You can check your current variables, edit them and add new variables.

I am running a Swedish installation of Windows 7.

To read them from Visual Basic, you just use the GetEnvironmentVariables function to retrieve the collection of registered variables. This example is written in VBx (Visual Basic 10):

Console.WriteLine(
   Environment.GetEnvironmentVariables().
      Item("PROCESSOR_REVISION").ToString())

Remember, when you write code to manipulate this collection, adding or changing values, you would normally want your code to run as a custom step in an MSI file, and not in a regular EXE.

Categories: Visual Basic 10.

Visit ACNE, view source

Visit http://www.acnestudios.com/ and view the source of their web page. There you have a small challenge for a web developer.

Thanks for the tip, Staffan!

Categories: Geeky.

Calling C functions

Like I mentioned earlier, functions that only are exposed through an external .NET interface are unreachable from PowerShell, but can be called using reflection. But how about C functions?

This is not a problem at all. Like always when you attempt to call a C function in a DLL, you must know how it is exposed. This is not unique for PowerShell. The name of the link library, the name of the entry point, and the parameter types. This gives you a huge number of functionality ready to call, including third party libraries and the Windows API.

I am going to use PowerShell to move the mouse cursor to location 100, 100 (left, top). The SetCursorPos function takes two integer values (X and Y) and returns a boolean. According to the Windows API documentation, the function resides in a library called User32.dll.

One way to do this, is to write Visual Basic code, use PowerShell to compile it to an assembly, and then use reflection to call it. But there is another way.

Create one array of arguments, and an array of argument types. In my case, since I’m calling the SetCursorPos function, this is what I need:

$parameterTypes = [UInt32], [UInt32]
$parameters = 100, 100

Then, the rest of the code is something written by Jouko Kynsijärvi, that Lee Holmes used to make the Invoke-Win32 function. This is my complete code. Three lines! Check this out!

#The parameter types.
$parameterTypes = [Int], [Int]

#The arguments.
$parameters = 100, 100

#The call. Library, return type, function name, types and values.
Invoke-Win32 "User32.dll" ([Bool]) "SetCursorPos" $parameterTypes $parameters

The rest of the listing is the definition of the Invoke-Win32 function that I extracted from this Lee Holmes’ post.

As you run this script, note how the mouse cursor jumps up to the upper left corner, 100 pixels from the left edge, 100 pixels from the top.

(I have a huge smile across my face when I’m writing this.)

Categories: PowerShell.

Tags:

.NET and speed: An int is just an int

So what is true about .NET and preformance? As long as you treat the an int as an int, there is no COM overhead. From a new post by Roger Alsing:

.NET have specific IL op codes in order to deal with primitives, and those opcodes will translate to pure machine code.

Also:

The value hex 7B (dec 123) is moved directly into the memory slot for the local variable.

Check out Roger’s blog.

Categories: Microsoft .NET.

My bits on evolution, part 5

Some of my bits for the Swedish Skeptic Podcast, Skeptikerpodden, on evolution and creationism, in Swedish.

Några av mina bidrag till svenska Skeptikerpodden om evolution och kreationism, på svenska.

13. William Dembski och kopplingen till kreationismen (från Skeptikerpodden 30/11 2010)

14. Kreationistpropaganda från Bibelfokus.se (del 1 av 3) (från Skeptikerpodden 21/12 2010)

15. Kreationistpropaganda från Bibelfokus.se (del 2 av 3) (från Skeptikerpodden 11/1 2011)

FöregåendeNästa

Categories: Science.

Tags:

Create an exe using PowerShell

This is, from what I know, the lest code you will need to write, to make PowerShell create a exe-file that do what you want it to do. It uses the VB compiler that is installed together with the .NET Framework together with the VB-specific CreateCompiler function, also installed with the .NET Framework.

Before you run it, make sure that the folder you write your exe to really exists. In my case, C:\temp.

First, let’s load an assembly. Remember, no line breaks here.

#Load the Visual Basic assembly go get the code
#that creates a compiler.
[System.Reflection.Assembly]::Load("Microsoft.VisualBasic, Version=8.0.0.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")

Then we create the objects we need. The second line will cause some problems. The object returned by the CreateCompiler function has a method that isn’t exposed, so we can’t call it directly. Also note that we are specifying an output path here.

$VB = New-Object Microsoft.VisualBasic.VBCodeProvider
$Compiler = $VB.CreateCompiler()
$Params = New-Object System.CodeDom.Compiler.CompilerParameters
$Params.GenerateExecutable = $true
$Params.OutputAssembly = "C:\temp\myprogram.exe"

This is the code I want in my exe:

[String]$S = "Imports System`n"
$S = $S + "Module MyModule`n"
$S = $S + "Sub Main(ByVal Args() As String)`n"
$S = $S + "Console.WriteLine(`"Hello! Press Enter!`")`n"
$S = $S + "Console.ReadLine()`n"
$S = $S + "End Sub`n"
$S = $S + "End Module`n"

Now, I must use reflection to call the unexposed method. In C# or VB, this is not a problem because we can use interfaces. PowerShell can’t. Since the method expects two arguments, I will create an array with the two elements. Then, the Invoke method takes the object where the function resides and the arguments. Typing is important so that the correct function overload will be found.

#Extract the method "CompileAssemblyFromSource". (No line break here!)
$CompileMethod=
[System.CodeDom.Compiler.ICodeCompiler].GetMethod("CompileAssemblyFromSource")

#We must pass in the parameters and the source
#when calling.
$Args = New-Object System.Object[] 2
$Args[0] = [System.CodeDom.Compiler.CompilerParameters]$Params
$Args[1] = $S
$Res = $CompileMethod.Invoke($Compiler, $Args);

$VB.Dispose()

Now, you have your own executable file that greets you when you start it!

Categories: PowerShell.

Tags: