.NET Windows API Library (Cjwdev.WindowsApi) Vesion 2.2 Released

June 12, 2011 — 17 Comments

There are not that many changes in this release as I was only updating it for my own use really but I figured other people may benefit from the new API definitions and managed methods included.

For anyone that doesn’t know what Cjwdev.WindowsApi is – it is a .NET DLL I have written that contains definitions for several native Windows APIs (80 to be precise) that enables you to do things you cannot do in the .NET framework already. As well as the raw API signatures, it also includes managed .NET methods that wrap a lot of these APIs up into methods that are easy to use from .NET code. So you can easily use these methods even if you have absolutely no experience calling Windows API functions from .NET. For more information and examples of what is included in the library see the various posts here: https://cjwdev.wordpress.com/category/cjwdev-windowsapi/

Anyway, here is a list of what is included in this latest release:

  • The following API definitions were added to the ApiDefinitions class: WTSGetActiveConsoleSessionId, WTSQueryUserToken, CreateProcessAsUser, DestroyEnvironmentBlock, CreateEnvironmentBlock, AllocConsole, FreeConsole, AddFontResource, RemoveFontResource
  • InstallFontForCurrentSession – Installs a font for the current session only (does not require admin permissions)
  • RemoveFontForCurrentSession – Removes a font from the system font table for the current session only (does not require admin permissions)
  • Overloaded versions of RenewIpAddresses and ReleaseIpAddresses that let you choose to ignore errors (so that if one NIC cannot be renewed/released for some reason then it will continue to attempt the operation on other NICs)

and here is the download link (make sure you extract the XML file to the same location as the DLL so that you get intellisense information for each method):

http://www.cjwdev.co.uk/DeveloperComponents/Cjwdev-WindowsAPI/Cjwdev.WindowsApi.zip

17 responses to .NET Windows API Library (Cjwdev.WindowsApi) Vesion 2.2 Released

  1. 

    Hi, it´s seems very interesting your Component.
    I would like to know, if it’s possible, how-to install a true type font in runtime, without admin privileges.
    Thanks in advanced.

    • 

      Are you asking how it actually works or asking for an example of how to use it to do that?

      • 

        Hi, thanks for your fast answer.
        At first I was looking for an example, but i lost a little time searching for the option InstallFontForCurrentSession and found it at NativeOperatingsystem.
        Apparently is what I’m looking for:
        – I have a program made in Visual Basic 2008 Express Edition and is working at work without having admin privileges;
        – I’m trying to use true type fonts in my program, that are not installed on pcs at work;
        – With your component i believe that it’s possible to install those fonts at startup, and then become useful to my program;
        – I’m trying right now, that’s why i don’t have a final answer.

        Thanks for your help!
        Sorry my English (not my first language!)

  2. 

    Hi, can’t answer yet!
    I’m facing a new problem: can’t use some fonts in visual basic at design time because it gives me a error: “Only True Type Fonts are supported”.
    I’m trying to set the font Label1 with a font that i like, but it gives me that error. The same for other three true type fonts. Strange.
    I’ll let you know later…

  3. 

    Hi again, sorry for take your time.
    Some font that I’m trying to use are not supported bu visual basic 2008 express edition. So don’t need to install them with your component. Thanks anyway!

  4. 

    Hi,

    Is it possible to open a treeview slowly from top to bottom in vs 2010 wpf ??

    Thanks

  5. 

    I tested CreateProcessAsUser function with windows service and this works fine.
    Except I cant use arguments. It there a way to use CreateProcessAsUser with arguments??

    Thanks

  6. 
    mohdassfarizalsalim February 4, 2013 at 20:18

    Yup read that MSDN and I have lost count trying to get this right:

    WindowsApi.CreateProcessAsUser(UserTokenHandle, “”, “””C:\WINDOWS\system32\cmd.exe”” “”/C echo test”””, IntPtr.Zero, IntPtr.Zero, False, 0, IntPtr.Zero, Nothing, StartInfo, ProcInfo)

    Is there a mistake here?

    • 

      This is how I would do it:

      WindowsApi.CreateProcessAsUser(UserTokenHandle, Nothing, """C:\WINDOWS\system32\cmd.exe"" ""/C"" ""echo"" ""test""", IntPtr.Zero, IntPtr.Zero, False, CREATE_UNICODE_ENVIRONMENT Or CREATE_NEW_CONSOLE, IntPtr.Zero, Nothing, StartInfo, ProcInfo)

      Although I would also recommend using the CreateEnvironmentBlock API to create the user’s environmental variables and passing that in to the 3rd to last parameter instead of Nothing. Some programs won’t work properly if the user’s environment isn’t setup correctly.

  7. 
    mohdassfarizalsalim February 5, 2013 at 05:34

    Still no lock =(
    I cant get CREATE_UNICODE_ENVIRONMENT Or CREATE_NEW_CONSOLE declared
    FYI, I’m developing new programmer….so here my full code

    without argument work fine….hope this helps. Thanks

    ——————————————————-
    Module Module1
    Dim WindowsApi As New WindowsApi

    Function run_as(ByVal apps_path As String, ByVal arg As String) As Boolean

    Try
    Dim UserTokenHandle As IntPtr = IntPtr.Zero
    WindowsApi.WTSQueryUserToken(WindowsApi.WTSGetActiveConsoleSessionId, UserTokenHandle)
    Dim ProcInfo As New WindowsApi.PROCESS_INFORMATION
    Dim StartInfo As New WindowsApi.STARTUPINFOW
    StartInfo.cb = CUInt(Runtime.InteropServices.Marshal.SizeOf(StartInfo))

    If arg = “” Then
    WindowsApi.CreateProcessAsUser(UserTokenHandle, apps_path, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, False, 0, IntPtr.Zero, Nothing, StartInfo, ProcInfo)
    Else
    WindowsApi.CreateProcessAsUser(UserTokenHandle, Nothing, arg, IntPtr.Zero, IntPtr.Zero, False, 0, IntPtr.Zero, Nothing, StartInfo, ProcInfo)
    End If

    If Not UserTokenHandle = IntPtr.Zero Then
    WindowsApi.CloseHandle(UserTokenHandle)
    End If
    Return True
    Catch ex As Exception
    Return False
    End Try

    End Function

    Sub Main()

    ‘run_as(“C:\WINDOWS\system32\cmd.exe”, “”)
    run_as(“”, “””C:\WINDOWS\system32\cmd.exe”” “”/C”” “”echo”” “”wakaka”””)
    Console.ReadLine()
    End Sub

    End Module

  8. 
    mohdassfarizalsalim February 5, 2013 at 12:19

    After leaving my computer for couple of hours and play with my 9 months baby boy, watching tv and do other things… I finally get this right. I found my problem after I write error to log file…should do this first than retrying blindly….

    And I use this page .NET Windows API Library (Cjwdev.WindowsApi) … Hope this help someone like me =)


    Function run_as(ByVal fpath As String, ByVal farg As String) As Boolean
    Dim UserTokenHandle As IntPtr = IntPtr.Zero
    Dim EnvironmentBlock As IntPtr = IntPtr.Zero
    Dim ProcInfo As New ApiDefinitions.PROCESS_INFORMATION

    Dim args() As String
    args = farg.Split(" ")
    Dim drvname As String = ""

    Dim cmdline As String = """" & fpath & """"

    For Each arg In args
    cmdline = cmdline & " """ & arg & """"
    Next

    Try
    Dim ConsoleSessionId As UInteger = ApiDefinitions.WTSGetActiveConsoleSessionId
    F.file_write("C:\", "run_as.log", "Console session ID = " & ConsoleSessionId, 1)

    F.file_write("C:\", "run_as.log", "Attempting to get handle to primary access token of console session user...", 1)
    Dim QueryTokenResult As Boolean = ApiDefinitions.WTSQueryUserToken(ConsoleSessionId, UserTokenHandle)
    If QueryTokenResult AndAlso Not UserTokenHandle = IntPtr.Zero Then
    F.file_write("C:\", "run_as.log", "Attempting to get handle to primary access token of console session user...", 1)
    Else
    F.file_write("C:\", "run_as.log", "Failed to get handle to primary token, the last error reported was: " & New ComponentModel.Win32Exception().Message, 1)
    Exit Function
    End If

    F.file_write("C:\", "run_as.log", "Creating environmental variable block for user...", 1)
    Dim CreateEnvironmentResult As Boolean = ApiDefinitions.CreateEnvironmentBlock(EnvironmentBlock, UserTokenHandle, False)
    If CreateEnvironmentResult AndAlso Not EnvironmentBlock = IntPtr.Zero Then
    F.file_write("C:\", "run_as.log", "Successfully created environmental variable block", 1)
    Else
    F.file_write("C:\", "run_as.log", "Failed to create environmental variable block for user, the last error reported was: " & New ComponentModel.Win32Exception().Message, 1)
    Exit Function
    End If

    Dim StartInfo As New ApiDefinitions.STARTUPINFO
    StartInfo.cb = CUInt(Runtime.InteropServices.Marshal.SizeOf(StartInfo))

    F.file_write("C:\", "run_as.log", "Attempting to launch process...", 1)
    Dim CreateProcessResult As Boolean = ApiDefinitions.CreateProcessAsUser(UserTokenHandle, Nothing, cmdline, IntPtr.Zero, IntPtr.Zero, False, ApiDefinitions.CREATE_UNICODE_ENVIRONMENT Or ApiDefinitions.CREATE_NEW_CONSOLE, EnvironmentBlock, "C:\WINDOWS\system32\", StartInfo, ProcInfo)

    If CreateProcessResult AndAlso Not ProcInfo.dwProcessId = 0 Then
    F.file_write("C:\", "run_as.log", "Process successfully launched in console session (Process ID = " & ProcInfo.dwProcessId & ")", 1)
    Else
    F.file_write("C:\", "run_as.log", "Failed to launch process, the last error reported was: " & New ComponentModel.Win32Exception().Message, 3)
    End If

    Finally
    'Clean up, close handles
    If Not UserTokenHandle = IntPtr.Zero Then
    ApiDefinitions.CloseHandle(UserTokenHandle)
    End If
    If Not ProcInfo.hProcess = IntPtr.Zero Then
    ApiDefinitions.CloseHandle(ProcInfo.hProcess)
    End If
    If Not ProcInfo.hThread = IntPtr.Zero Then
    ApiDefinitions.CloseHandle(ProcInfo.hThread)
    End If
    If Not EnvironmentBlock = IntPtr.Zero Then
    ApiDefinitions.DestroyEnvironmentBlock(EnvironmentBlock)
    End If
    End Try

    Dim WaitForExit As Boolean = True

    'Wait for the process to exit if that has been requested
    If WaitForExit AndAlso Not ProcInfo.dwProcessId = 0 Then
    Dim LaunchedProcess As Process = Nothing
    Try
    LaunchedProcess = Process.GetProcessById(CInt(ProcInfo.dwProcessId))
    Catch ex As ArgumentException
    F.file_write("C:\", "run_as.log", "Process has terminated: " & ex.ToString, 1)
    End Try
    If Not LaunchedProcess Is Nothing Then
    F.file_write("C:\", "run_as.log", "Waiting for process to exit...", 1)
    LaunchedProcess.WaitForExit()
    F.file_write("C:\", "run_as.log", "Process has terminated", 1)
    End If
    End If

    End Function

    But I have another problem… something like this works
    run_as(“C:\WINDOWS\system32\notepad.exe”, “C:\test.txt”)
    It will open a C:\test.txt in notepad

    But if I try this:
    run_as(“C:\run_script.bat”, “regedit”)

    This is sample of C:\run_script.bat

    echo off
    cls

    set ty=%1
    if "%ty%" == "runcmd" cmd
    if "%ty%" == "compmgmtmsc" compmgmt.msc
    if "%ty%" == "appwizcpl" appwiz.cpl
    if "%ty%" == "ncpacpl" ncpa.cpl
    if "%ty%" == "regedit" start regedit

    I can see command prompt window is open and immediately close.
    It only work if I change into this

    if "%ty%" == "regedit" start C:\Windows\System32\regedt32.exe

    Any idea what when wrong?

  9. 
    mohdassfarizalsalim February 5, 2013 at 12:31

    Chris, i modified your code from StartInConsoleSession.exe
    Hope you dont mind. I tried StartInConsoleSession.exe but always get this error:

    C:\StartInConsoleSession.exe C:\Windows\System32\cmd.exe

    StartInConsoleSession.exe
    Version 1.0.0.0
    Developed by Chris Wright (cwright@cjwdev.co.uk)

    Command line = “C:\Windows\System32\cmd.exe”
    Wait for exit = False
    Attempting to get console session ID…
    Console session ID = 1
    Attempting to get handle to primary access token of console session user…
    Failed to get handle to primary token, the last error reported was: A required privilege is not held by the client

    • 

      Yeah you can only run that code if you’re running as Local System (I did explain that in the blog post where I provided the link to StartInConsoleSession)

  10. 

    Creating shares does not seem to work with x64. Any ideas?

    • 

      Unfortunately not, I never could get it working from a 64 bit process. I keep meaning to revisit it and figure it out but haven’t had chance. It will work fine on a 64 bit OS if you just make your process 32 bit though (e.g change the CPU type to x86 rather than AnyCPU or x64)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s