Tuesday, October 11, 2005

Microsoft Remote Desktop Control in VB.Net

At work we use Terminal Services a great deal. It allows us to use many PC’s all without getting up or having our cubes filled with them. Also we often have a “when you’re awake you work” processing load so we’re connecting from home, vacation, the parents, hotels, etc, etc, all the time. Terminal Services/Remote Desktop all makes this possible

To date we’ve used the Terminal Services MMC snap-in to manage our connections. While this works, it’s pretty bare bones and there are few configuration options.

So as a side/personal project I’ve want to create our own TS connection wrapper app. I had some time tonight, so I started with the R&D.

Of course I want to build this in VB7.1…

Well long story short, it’s been a pain. The hard part is getting the RD control to host on a form. The funny part is that it’s easy in VB6… Dogh!

Googling this for a while helped me find a couple sites that really helped me over this hump. I wanted to make sure I captured them here (leach a little their data in case they go away) for any future need.

Between the two of these and some minor open heart surgery on the VB.Net sample I now have a working starting point for my app…

Failure to add msrdp.ocx control to C#.NET or VB.NET form
“… First of all, I would like to confirm my understanding of your issue. From your description, I understand that when you have drag and drop a Terminal Services Control on a windows form, a compiler error was generated. If there is any misunderstanding, please feel free to let me know.

Based on my research, this is a known issue. The wrapper generater fails to
generate correct method for returning an enum value. Here is a workaround.

1. md c:\temp
2. cd c:\temp
3. %<SDK bin directory>%\aximp.exe %windir%\system32\mstscax.dll
This will generate MSTSCLib.dll and AxMSTSCLib.dll.
Make sure Interop.MSTSCLib.dll and AxInterop.MSTSCLib.dll have been deleted in the obj and bin\Debug directories.
4. Copy the generated files (without renaming) - MSTSCLib.dll and AxMSTSCLib.dll into the project's obj directory.
5. In the project's references, add MSTSCLib.dll and AxMSTSCLib.dll from the obj directories.
6. Now, instead of drag-drop'ing the control from the toolbox, write code to add the control:
Goto Form.cs code view
Declare: private AxMSTSCLib.AxMsTscAx axMsTscAx1;
In InitializeComponent:
this.axMsTscAx1 = new AxMSTSCLib.AxMsTscAx(); ((System.ComponentModel.ISupportInitialize)(this.axMsTscAx1)).BeginInit();

//
// axMsTscAx1
//
this.axMsTscAx1.Enabled = true;
this.axMsTscAx1.Location = new System.Drawing.Point(58, 17);
this.axMsTscAx1.Name = "axMsTscAx1"
this.axMsTscAx1.OcxState =
((System.Windows.Forms.AxHost.State)(resources.GetObject("axMsTscAx1.OcxStat
e")));
this.axMsTscAx1.Size = new System.Drawing.Size(192, 192);
this.axMsTscAx1.TabIndex = 1;
....

this.Controls.Add(this.axMsTscAx1);
((System.ComponentModel.ISupportInitialize)(this.axMsTscAx1)).EndInit();

HTH.

Kevin Yu”

http://dev.remotenetworktechnology.com/news.htm
“… MsRdpNET  - a simple demo of wrapping Microsoft's redistributable RDP web client inside a VB.NET project. …”


Here’s the “magic” from the above VB sample (which can be thought of as a C# translation of the above forum post).

“Friend WithEvents AxMsRdpClient21 As AxMSTSCLib.AxMsRdpClient

<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
….
  Me.AxMsRdpClient21 = New AxMSTSCLib.AxMsRdpClient
  CType(Me.AxMsRdpClient21, System.ComponentModel.ISupportInitialize).BeginInit()
  Me.SuspendLayout()
  '
  'AxMsRdpClient21
  '
  Me.AxMsRdpClient21.Dock = System.Windows.Forms.DockStyle.Top
  Me.AxMsRdpClient21.Enabled = True
  Me.AxMsRdpClient21.Name = "AxMsRdpClient21"
  Me.AxMsRdpClient21.OcxState = _
CType(resources.GetObject("AxMsRdpClient21.OcxState"), System.Windows.Forms.AxHost.State)
  Me.AxMsRdpClient21.Size = New System.Drawing.Size(792, 600)
  Me.AxMsRdpClient21.TabIndex = 0

‘…

  CType(Me.AxMsRdpClient21, System.ComponentModel.ISupportInitialize).EndInit()
  Me.ResumeLayout(False)

End Sub”

When everything is right (with both the aximp’ed assemblies and the VB code), you’ll see the RDP Client control on the form at runtime and be ready for the races…

23 comments:

Anonymous said...

Hey Greg,

Can you post your final code, sounds cool

Greg said...

I wish I could... But since this was a work project, there's IP issues involved. Issues that keep me from release much of my code... sigh

BUT I can say the in VS2005/VB8 the Remote Desktop control is MUCH easier to use. There's no magic needed, adding the control just works...

Anonymous said...

No problem Greg I understand fully,

One question for you though, which RDP control are you using in VS2005?

Are you using the ocx or did you still use AxMSTSCLib?

Greg said...

I'm referencing MSTSCAX (AxMSTSCLib)... (aka the "Microsoft Terminal Services Active Client 1.0 Type Library" once added as a reference).

I'm not using the OCX, which I believe also means I'm tied to XP and greater. Which in my case is okay since I'm using some XP+ API's anyway (like the very cool PrintWindow api)...

I hope this helps,
Greg

Anonymous said...

Greg,

Helps a ton, I am also stuck in the MS world.

I will let you know how it goes as I try this over the weekend.

Once again,
Thanks for the help

Anonymous said...

I like your code for RDP and vb.net but running the MSRDPNet app i get the error

Type 'AxMSTSCLib.AxMsRdpClient2' is not defined.

Does anyone know how to fix this, The fix is probably stairing me right in the face ?

Greg said...

This is going to sound lame, but I've seen this before but for the life of me I can't remember the solution or where I saw it....

I've done, as I sure you have, the google thing and nothing seems to ring a bell.

A couple thoughts...
a) You're on XP (or 2k3, etc)?

b) Check out www.codeplex.com/terminals, which is a cool project to replace the TS MMC/Remote Desktop, etc (like my work project which sparked the above code, but luckily they can/are OSS)

c) Are you using .Net 2/VS2005? I've found the remote desktop control is much easier to use there.

d) The only thing I seem to remember about resolving this issue was related to how the type library was generated and/or regenerated... (Like I said... lame, I know)

I wish I could have been of more help.

Unknown said...

very helpful -

are you able to run a start program from your app? i can't seem to get rdpSession.SecuredSettings to set correctly?

TIA

Greg said...

I apologize but I'm not sure I understand the question...

When connecting to the remote machines, everything in their startup folders/registry keys run fine.

When initiating the connection to the remote machines I'm using the AxMSTSCLib.AxMsRdpClient.Server, AxMSTSCLib.AxMsRdpClient.Name, AxMSTSCLib.AxMsRdpClient.Doman and AxMSTSCLib.AxMsRdpClient.AdvancedSettings2.ClearTextPassword (since I'm storing the passwords, I've taken additional steps to encrypt them and only decrypt them as needed) plus set other basic properties (RedirectDrives, etc) and then call Connect.

Another cool Remote Desktop solution that uses the same ActiveX control (with source) you should check out is the Terminals project (if this had been around I'm not sure I'd have built mine... ;)

www.CodePlex.com/Terminals

Unofficial/Official Latest Version


I hope this helps a little,
Greg

Christian said...

Hi Greg

thanks for sharing this with us.
I've a question .. do you have an idea how to sign the generated AxMSTSCLib.dll using a strong name key?

Christian

Greg said...

@Christian

Sorry, but that's something I'd have to google for too...

leonita said...

hi greg,
im new in vb.net...and i want to build a remote desktop application, so i can controled client's PC...wht i hv tried now is using socket...wht i want is i can see my client desktop fully...can i do it with vb.net...can u gv me some advices...thx b4

Greg said...

@leonita

I wouldn't write your own Remote solution... I'd leverage Remote Desktop. (So need need to sockets, etc).

There are some details in the above post, but in short, you take the Remote Desktop component, add to your VS toolbar (i.e. as a component), then add it to your WinForm, then control that to connect to a another machine.

With Visual Studio 2008 it's even simplier that the above process. Just add a component, browse to the OCX...

Once you get it onto your VS Toolbar you drag it onto the form and go from there...

leonita said...

hy...thx for ur responsed..
iam using mstscax.dll..and i already add the component..and i write this code:
Dim rdp As MSTSCLib.IMsRdpClient2 = New MSTSCLib.MsRdpClient2()
rdp.Server = "ipserver"
rdp.UserName = "username"
rdp.FullScreen = True
rdp.DesktopHeight = 300
rdp.DesktopWidth = 300
rdp.Connect()

its work..but when i run the application, the client's user of the current pc logged off..
wht i want is client dont need to know when i remote their pc..
thx b4

Greg said...

@leonita
Yep, that's the way RDP/Remote Desktop works and there's no way of working around that.

If that's the feature you need, you'll need to look into another technology (something like VNC).

I've not needed that kind of feature so can't provide you much guidance there...

leonita said...

VNC??
mmmmhmm...is it still use mstscax.dll?? or i hv to find another VNC lib...
can u give me some advice here..how to starts with VNC..
thank you so muuuuuuuuuccchhh...GBU

Greg said...

No VNC is a totally different remote technology and does not mstscax.dll.

mstscax.dll (aka Remote Desktop) will not do what you seem to need, so you're going to have to use some other technology.

I've not needed to use VNC, so really can't provide much help. There's a ton of VNC stuff out there (just search on VNC).

You should also look at mRemote and Terminals, both of which include VNC support and both of which are open source...

leonita said...

hiiiiiii..thx a lot Greg...
-hv a nice day..GBU
ps:sorry about my poor english.hehe

nezam said...

hi Greg.,
Thanks.,
I tried RDP it worked well but i was not happy with RDP as it logs off the CLient system.

At last i came to know that if i use RDP. the client's system will log off.
and now i have to develop VNC thing.
and I will GOOGLE about from Now.
Thanks DUDE:-)
Keep it Up....
why cant u start a new site

nezam said...

hi Greg,
I need to know . if i need to built a software like Team viewer.
whether i have to use VNC or Remote Desktop.
I am getting confused.

Greg said...

@nezam.
As you've found, RDP is meant for one person to one session. It's not meant for more than one person being connected to a given session at a time.

So if you are writing some kind of viewer/sharing/etc application then you'll need to using some other tech.

I've used VNC for that so can't really say if it fits that bill or not...

Anonymous said...

Greg, it sounds like I am working on a similar project as you were back in 2005. I have tried to follow your suggestions as there is not much otherwise available on the net and I continue to get an error message that the Active X component could not be created. Do you have any suggestions?

Greg said...

@Kurt,
One thing I'd do is check out a project or two where they are doing this already, so you can see working code (since I can't share mine... sigh).

Funny, but I have two projects right at the top of my head... ;)

Terminals
mRemote

Both include RDP (plus tons more) support and both are OSS/Source Available.

Grabbing these and checking out how they are doing RDP might help you figure out why your implementation isn't working...