Jump to content
kurtdejaeger

Create plugin in Visual Studio (vb)

Recommended Posts

Hello,

 

I want to create a plugin to get system information (hardware info) from an 2008 server.

I have Visual Studio, but I really don't know how to start.

Can someons point my in the right direction or create a sample to write an vb class?

 

Public Class Class1

        ??????????
End Class

 

Manu thanks

Kurt

 

 

I have the vb code here:

 

strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colSettings = objWMIService.ExecQuery _
("Select * from Win32_OperatingSystem")
For Each objOperatingSystem in colSettings
Wscript.Echo "OS Name: " & objOperatingSystem.Name
Wscript.Echo "Version: " & objOperatingSystem.Version
Wscript.Echo "Service Pack: " & _
objOperatingSystem.ServicePackMajorVersion _
& "." & objOperatingSystem.ServicePackMinorVersion
Wscript.Echo "OS Manufacturer: " & objOperatingSystem.Manufacturer
Wscript.Echo "Windows Directory: " & _
objOperatingSystem.WindowsDirectory
Wscript.Echo "Locale: " & objOperatingSystem.Locale
Wscript.Echo "Available Physical Memory: " & _
objOperatingSystem.FreePhysicalMemory
Wscript.Echo "Total Virtual Memory: " & _
objOperatingSystem.TotalVirtualMemorySize
Wscript.Echo "Available Virtual Memory: " & _
objOperatingSystem.FreeVirtualMemory
Wscript.Echo "OS Name: " & objOperatingSystem.SizeStoredInPagingFiles
Next
Set colSettings = objWMIService.ExecQuery _
("Select * from Win32_ComputerSystem")
For Each objComputer in colSettings
Wscript.Echo "System Name: " & objComputer.Name
Wscript.Echo "System Manufacturer: " & objComputer.Manufacturer
Wscript.Echo "System Model: " & objComputer.Model
Wscript.Echo "Time Zone: " & objComputer.CurrentTimeZone
Wscript.Echo "Total Physical Memory: " & _
objComputer.TotalPhysicalMemory
Next
Set colSettings = objWMIService.ExecQuery _
("Select * from Win32_Processor")
For Each objProcessor in colSettings
Wscript.Echo "System Type: " & objProcessor.Architecture
Wscript.Echo "Processor: " & objProcessor.Description
Next
Set colSettings = objWMIService.ExecQuery _
("Select * from Win32_BIOS")
For Each objBIOS in colSettings
Wscript.Echo "BIOS Version: " & objBIOS.Version
Next

 

Share this post


Link to post
Share on other sites

Hello kurtdejaeger,

 

Welcome to the world of programming. I understand you are a beginner so I have converted your vb script into a valid PC Monitor plugin in two (visual studio compatible) programming languages so that you can see the differences between them and maybe learn a bit from them.

 

I hope that you will continue researching programming after you finish your first plugin. Also if you ever need help on creating a plugin please ask here and I will do my best to help you.

 

You will find a Release folder that contains both of the plugin versions in binary format. Both of them do the same thing.

 

Also check out API documentation that will help you get started on writing plugins. Click here.

 

Good Luck,

Paul.

Share this post


Link to post
Share on other sites

Due to request I have updated the plugin to support paged view. Both projects (VB and CS) support paged view configuration.

 

Paul.

 

Edit: I have fixed a mistake in the plugin. I was requiring an invalid pc monitor version. Download the new release.

PaulCsiki.SystemInfoPlugin.zip

Share this post


Link to post
Share on other sites

Hey Paul ... Many thanks for scripts ... But I cannot load them in the Plugin option.  I'll get an empty window.  When I try with my sample code, it works.

So the moment to want to load the plugin, the browser folder (after selecting your plugin in fileselectfolder) stays empty...

But I can open in it in Visual Studio ... Great plugin ... I allready searched within the wanted WMI Classes for more info and option.

It really helped me a lot and how to start writing my own script.

Many many ... many thanks :-)

Allthough I want to see that second version, about the paged view and how it works ...

 

I allready have another question: how to get the external ip address from script... I thinks its not that difficult.  But I saw that the default monitor (dashboard via http) gives you the servers external ip address.  Which value do I have to export?

 

Kind regards

 

Kurt De Jaeger

Share this post


Link to post
Share on other sites

Hello Paul,

I've come to another question: ... when you install a plugin, it comes at the bottom of the page ... No problem here ... But how do I get to open (for example IE to the ip-address of that server)

So 1. How to make an clickable item or button or whatsoever ...

And 2. directly open IE to ip-address

 

Thanks

 

Kind Regards

 

Kurt De Jaeger

Share this post


Link to post
Share on other sites

In answer to the first question, the original plugin was for a different version and plugin was updated by Paul Csiki. Please download again. Alternatively, you could download my version (digbyp).

 

We have also discovered (and have the fix already) whereby if one of the fields is 'blank' the plugin will not show to use. I only discovered this when i was adding more to my verson and Paul Csiki provided the resolution

 

regards

 

Paul Digby

Share this post


Link to post
Share on other sites

It could be possible on a future version.

 

 

Hello Paul,

I've come to another question: ... when you install a plugin, it comes at the bottom of the page ... No problem here ... But how do I get to open (for example IE to the ip-address of that server)

So 1. How to make an clickable item or button or whatsoever ...

And 2. directly open IE to ip-address

 

Thanks

 

Kind Regards

 

Kurt De Jaeger

Share this post


Link to post
Share on other sites

Hi paul ...

Thnx for the answer... but I'm a bit in a hurry: I would like to buy for subscription, but I need to make a presentation of the futures and to be able to do this is very important.  Thats why I don't know when thsis future is going to able.  So thats why I thought to write it, so that we already have this option of possiblility.

 

I allready have writen some script that adds a button in stead of info, but it doesn't do anything...

 

 

Kind Regards

Kurt

Share this post


Link to post
Share on other sites

hehe ... I'm not a master at writing scripts, but I really don't know what's all about... I've looked at the API documentation, and I've found the void "PageCommandReceived()" item, but don't know how to start.  I'll will take a look at your plugins and hope to found an answer for my simple question...

Kind Regards

Kurt

Share this post


Link to post
Share on other sites

C#

public override void PageCommandReceived(int pageId, int commandId)
{
    // your code here
}

VB.NET:

Public Overrides Sub PageCommandReceived(ByVal pageId As Integer, ByVal commandId As Integer)
    // your code here
End Sub

Share this post


Link to post
Share on other sites

Hey Paul ... This is my code, but it doesn't do anything.

I get it to load and I can see it in the website (MyComputers https://my.pulseway.com/)

And when I click it, it says "RemoteControl plugin was send", but nothing happends ... It doens't open IE as a test.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using MM.Monitor.Client;

namespace RemoteSupport
{
    public class Plugin : ClientPlugin

    {
        private const int COMMAND_REMOTE_SUPPORT = 1;   

    
        public override string GetPluginName()
        {
            return "Remote Support";
        }

        public override string GetPluginDescription()
        {
            return "This plugin opens RDP to external IP";
        }

        public override Groups GetAdditionalComputerDetails()
        {
            Groups container = new Groups();
            Group mainGroup = new Group("Remote Support");
            mainGroup.Items.Add(new CommandItem(COMMAND_REMOTE_SUPPORT,"Remote Support"));
            container.Add(mainGroup);
            return container;
        }

        public override void PageCommandReceived(int pageId, int commandId)
        {
            if (commandId == 1)
            {
                System.Diagnostics.Process proc = new System.Diagnostics.Process();
                proc.EnableRaisingEvents = false;
                proc.StartInfo.FileName = "mstsc.exe";
                proc.Start();

            }
        }
            
     }
        
}

Share this post


Link to post
Share on other sites

Hello Kurt,

 

Your code is correct however you missed two things:

 

  1. You should use shell execute on your processes to 'unbind' them from the parent process.
  2. Starting from windows vista a windows service cannot touch a user session unless some hardcore impersonation API calls.

Basically you need to ask yourself the following questions:

  • On which user sessions your service is supposed to run the application?
  • What if no user is logged in?

Consult these posts:

 

Let me know if you get stuck again.

 

Good luck mate.

Paul.

Share this post


Link to post
Share on other sites

Hey Paul,

The whole meaning of this is to, open locally an mstsc.exe to the external ip address

I have some test servers, and I just want to click an extra plugin button to open "mstsc -external ip adress" of that server.

All the servers are logged on (as admin) or logged out.  But I don't think this is an issue, because the mstsc.exe is opened from my laptop ... From which I want to remote access it.

So basically I'm logged to my laptop now and via webUI looking at my servers.

 

If this is possible then I will try it with shell execute...

 

Many thanks

 

Till soon :-)

 

Kind regards

Kurt

Share this post


Link to post
Share on other sites

Modified to use ShellExecute, but still nothing happends ... Still got the message that plugincommand is send, but nothing ... damn

How hard can it be to open mstsc.exe local on my laptop from which i'm working on ...

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using MM.Monitor.Client;

namespace RemoteSupport
{
    public class Plugin : ClientPlugin

    {
        private const int COMMAND_REMOTE_SUPPORT = 1;   

    
        public override string GetPluginName()
        {
            return "Remote Support";
        }

        public override string GetPluginDescription()
        {
            return "This plugin opens RDP to external IP";
        }

        public override Groups GetAdditionalComputerDetails()
        {
            Groups container = new Groups();
            Group mainGroup = new Group("Remote Support");
            mainGroup.Items.Add(new CommandItem(COMMAND_REMOTE_SUPPORT,"Remote Support"));
            container.Add(mainGroup);
            return container;
        }

        public override void PageCommandReceived(int pageId, int commandId)
        {
            if (commandId == 1)
            {
                ProcessStartInfo RDPexe = new ProcessStartInfo("mstsc.exe");
                RDPexe.UseShellExecute = true;
                Process.Start(RDPexe);
            }
        }
    }
        
}

Share this post


Link to post
Share on other sites

Hey Kurt,

 

I will update your code with a working version. I will post back when I finished. Give me an hour.

 

Thanks..

Share this post


Link to post
Share on other sites

Hey Paul ... that would be great ... ok I admit, i'm not an program writer ... So sorry for the disturbing.

I did some simple vb.net VB scripting and written small apps ... But not in C#.

And the syntax of this mobilepcmonitoring is specific.  I guess ...

I really want to buy a subscription and to access a server (installed client) via the external ip address, would be very helpfull for me.

Ok I can see the external ip adress, but when i click it (in the wbeUI) it opens maps.google.com ...

Just want a simple button to open mstsc.exe on the external ip address.

My 3 test servers are behind a firewall, which are configured port 3389 to be open for me.

Manually it works from my laptop so thats not it.

Kind Regards

Kurt

Share this post


Link to post
Share on other sites

Hello Kurt,

 

Add this class to your project:

using System;
using System.Runtime.InteropServices;

namespace Plugin1
{
    public static class Win32
    {
        [StructLayout(LayoutKind.Sequential)]
        private struct Security_Attributes
        {
            public Int32 Length;
            public IntPtr lpSecurityDescriptor;
            public Boolean bInheritHandle;
        }

        private enum Token_Type
        {
            TOKEN_PRIMARY = 1,
            TOKEN_IMPERSONATION = 2
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct Startupinfo
        {
            public Int32 cb;
            public String lpReserved;
            public String lpDesktop;
            public String lpTitle;
            public UInt32 dwX;
            public UInt32 dwY;
            public UInt32 dwXSize;
            public UInt32 dwYSize;
            public UInt32 dwXCountChars;
            public UInt32 dwYCountChars;
            public UInt32 dwFillAttribute;
            public UInt32 dwFlags;
            public short wShowWindow;
            public short cbReserved2;
            public IntPtr lpReserved2;
            public IntPtr hStdInput;
            public IntPtr hStdOutput;
            public IntPtr hStdError;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct Process_Information
        {
            public readonly IntPtr hProcess;
            public readonly IntPtr hThread;
            public readonly UInt32 dwProcessId;
            public readonly UInt32 dwThreadId;
        }

        private enum Security_Impersonation_Level
        {
            SECURITY_ANONYMOUS = 0,
            SECURITY_IDENTIFICATION = 1,
            SECURITY_IMPERSONATION = 2,
            SECURITY_DELEGATION = 3,
        }

        private const UInt32 MAXIMUM_ALLOWED = 0x2000000;
        private const Int32 CREATE_UNICODE_ENVIRONMENT = 0x00000400;
        private const Int32 NORMAL_PRIORITY_CLASS = 0x20;
        private const Int32 CREATE_NEW_CONSOLE = 0x00000010;

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern Boolean CloseHandle(IntPtr hSnapshot);

        [DllImport("kernel32.dll")]
        public static extern UInt32 WTSGetActiveConsoleSessionId();

        [DllImport("Wtsapi32.dll")]
        private static extern UInt32 WTSQueryUserToken(UInt32 sessionId, ref IntPtr phToken);

        [DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        private static extern Boolean CreateProcessAsUser(
            IntPtr hToken,
            String lpApplicationName,
            String lpCommandLine,
            ref Security_Attributes lpProcessAttributes,
            ref Security_Attributes lpThreadAttributes,
            Boolean bInheritHandle,
            Int32 dwCreationFlags,
            IntPtr lpEnvironment,
            String lpCurrentDirectory,
            ref Startupinfo lpStartupInfo,
            out Process_Information lpProcessInformation);

        [DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")]
        private static extern Boolean DuplicateTokenEx(
            IntPtr existingTokenHandle,
            UInt32 dwDesiredAccess,
            ref Security_Attributes lpThreadAttributes,
            Int32 tokenType,
            Int32 impersonationLevel,
            ref IntPtr duplicateTokenHandle);

        [DllImport("userenv.dll", SetLastError = true)]
        private static extern Boolean CreateEnvironmentBlock(
            ref IntPtr lpEnvironment,
            IntPtr hToken,
            Boolean bInherit);

        [DllImport("userenv.dll", SetLastError = true)]
        private static extern Boolean DestroyEnvironmentBlock(IntPtr lpEnvironment);

        /// <summary>
        /// Creates the process in the interactive desktop with credentials of the logged in user.
        /// </summary>
        public static void CreateProcessAsUser(String commandLine, String workingDirectory = null)
        {
            var dwSessionId = WTSGetActiveConsoleSessionId();
            var hUserToken = IntPtr.Zero;
            WTSQueryUserToken(dwSessionId, ref hUserToken);

            var sa = new Security_Attributes();
            sa.Length = Marshal.SizeOf(sa);

            var hUserTokenDup = IntPtr.Zero;
            DuplicateTokenEx(
                hUserToken,
                (Int32) MAXIMUM_ALLOWED,
                ref sa,
                (Int32) Security_Impersonation_Level.SECURITY_IDENTIFICATION,
                (Int32) Token_Type.TOKEN_PRIMARY,
                ref hUserTokenDup);


            if (hUserTokenDup != IntPtr.Zero)
            {
                var dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;

                var pEnv = IntPtr.Zero;
                if (CreateEnvironmentBlock(ref pEnv, hUserTokenDup, true))
                    dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
                else
                    pEnv = IntPtr.Zero;

                // Launch the process in the client's logon session.
                Process_Information pi;

                var si = new Startupinfo();
                si.cb = Marshal.SizeOf(si);
                si.lpDesktop = "winsta0\\default";

                CreateProcessAsUser(hUserTokenDup, // client's access token
                                    null, // file to execute
                                    commandLine, // command line
                                    ref sa, // pointer to process SECURITY_ATTRIBUTES
                                    ref sa, // pointer to thread SECURITY_ATTRIBUTES
                                    false, // handles are not inheritable
                                    dwCreationFlags, // creation flags
                                    pEnv, // pointer to new environment block 
                                    workingDirectory, // name of current directory 
                                    ref si, // pointer to STARTUPINFO structure
                                    out pi // receives information about new process
                    );
                DestroyEnvironmentBlock(pEnv);
            }
            CloseHandle(hUserTokenDup);
            CloseHandle(hUserToken);
        }
    }
}

Then in your application delete the page command received with command received (Only use page command received for commands received from a PageItem).

 

Use this code:

        public override void CommandReceived(int commandId)
        {
            if (commandId == 1)
                Win32.CreateProcessAsUser(@"C:\Windows\System32\mstsc /v:10.0.8.5", @"C:\Windows\System32");
        }

I didn't test this code on a machine with multiple sessions. I have no idea how it will manifest then.

 

Let me know if you need further help.

 

Paul.

Share this post


Link to post
Share on other sites

Oops: I forgot to update the namespace on the class. Change the namespace on the new class to match yours: Plugin1 -> RemoteSupport

 

Paul.

Share this post


Link to post
Share on other sites

While reading your replies made me realize you want a plugin on a computer change the bahavior and execute a process on the client computer / device. This is not supported and it is very dangerous if it would be. What if I share with you a computer that has a script that can download and execute a rootkit on your computer just by clicking on my plugin? Mobile PC Monitor doesn't do any code injection on client devices / computers. Plugins can only execute on the machines they are installed.

Share this post


Link to post
Share on other sites

Wauw ... first impression ... wauw ... Is this the whole code to just run mstsc.exe on my laptop ... hehe

 

Many many many thanks.

 

It opens mstsc !!!! .... OMG ... it seems rocketsience to write a code to open mstsc ... omg ...

But it works ...

 

Now I can go further getting the external ip addres of the viewing server.

Unless there is an string I can read directly from the client software?

 

Kind regards

 

Kurt

Share this post


Link to post
Share on other sites

External IP is not exposed by the pc monitor api. Btw your code to execute a process was fine but microsoft decided to make a developer's life a pain while working under a windows service. If you can wait 9 hours until I wake up and I am at work I will post a method that returns your public IP address.

Share this post


Link to post
Share on other sites

I've found some scripts that gets the external ip address, but which one will it be?  My own from my laptop location, or the one from the test server?

 

So, my first code was alright :-) ... Yeah long live microsoft ... It makes no sence sometimes ... Like pressing START to SHUTDOWN hé ...

 

Ok I'll wait a till tomorrow ... I will try also to get the script working with my small knowledge ...

 

Many thanks in advance

 

Kind Regards

Kurt

Share this post


Link to post
Share on other sites

Good morning Kurt, On my last reply I've told you that code will never execute on the client side ( your laptop ) but on the system that hosts your plugin. I will post the code that will get your external IP address when I get to work.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...