Mapping a Network Drive via Web Service?

A

Andrew Raastad

We have a very old COM/Active-X DLL that our web application (non-.Net) uses
to interact with the server, and to map a network drive to the server for
use through the web application. But we need to update this whole method as
this solution won't work as is on 64-Bit servers. While this web app is not
MS technology, it can interact with Web Services, so I thought making a .Net
Web Service would do the trick, but running into a little snag....

The original Com/Active-X DLL had a reference to something called
"WshNetwork". This it turns out is the "Windows Script Host Object Model"
(wshom.ocx).

Making a reference to this via COM Interop, it creates
"Interop.IWshRuntimeLibrary.dll" in the bin folder for me to use in the
application, so I can write some code that is more in line with the original
DLL:

Private Shared Sub MountVolume(ByVal Volume As String, ByVal NetworkPath
As String, ByVal UserName As String, ByVal Password As String)
Dim ws As New IWshRuntimeLibrary.IWshNetwork_Class
Try
If UserName.Length > 0 Then
ws.MapNetworkDrive(Volume, NetworkPath, Nothing,
CObj(UserName), CObj(Password))
Else
ws.MapNetworkDrive(Volume, NetworkPath)
End If

Catch ex As Exception
Throw New Exception(String.Format("MountVolume() Failed:
{0}{1}", vbCrLf, ex.Message))

End Try
End Sub

Private Shared Sub UnMountVolume(ByVal Volume As String, ByVal Force As
Boolean)
Dim ws As New IWshRuntimeLibrary.WshNetwork
Try
ws.RemoveNetworkDrive(Volume, CObj(Force))

Catch ex As Exception
Throw New Exception(String.Format("UnMountVolume() Failed:
{0}{1}", vbCrLf, ex.Message))

End Try
End Sub

And through this Interface I can even get a listing of the current network
drives on the machine:

Public Function GetMappedDrives() As String
Dim ws As New IWshRuntimeLibrary.IWshNetwork_Class
Try
Dim sb As New StringBuilder
Dim colDrives As IWshCollection = ws.EnumNetworkDrives
For i As Integer = 0 To (colDrives.Count - 1) Step 2
sb.Append(String.Format("{0} ", colDrives(i)))
Next

Return sb.ToString.Trim.Replace(" ", ",")

Catch ex As Exception
Throw New Exception(String.Format("GetMappedDrives()
Failed:{0}{1}", vbCrLf, ex.Message))

End Try
End Function


So, I create a new Web Service project and add the above three methods,
exposing each as a public <WebMethod()>. Then, I create a completely
separate win form app that has a "Map Drive" button, an "UnMap Drive"
button, and a "Get Drives" button. I add a reference to the web service and
then tie the three buttons to the respective exposed web methods. Running
the winform app, I click the Map Drive button and sure enough, the network
drive shows up in My Computer. Clicking the UnMap Drive button and the
drive disappears in My Computer. And clicking the Get Drives button gives me
a list of the drive letters that are network drives on my machine.

At this point I'm ecstatic.... I have a Web Service mapping and unmapping
network drives. So, I copy the web service over to my test server (a Win
2003 Server), make a web reference in my winform app to the test server, run
the winform app, and.... *boom*!

When clicking the MapDrive button (which passes "J:" for a drive letter, and
also the UNC path, and my username and password values) I get the following
error:

System.Web.Services.Protocols.SoapException: Server was unable to process
request. ---> System.Exception: MountVolume() Failed: The local device name
is already in use. (Exception from HRESULT: 0x80070055) at
NMSWebServices.Network.MountVolume(String Volume, String NetworkPath, String
UserName, String Password) at NMSWebServices.Network.MapDrive(String
DriveLetter, String UNCPath, String strDomain, String strUsername, String
strPassword) --- End of inner exception stack trace ---

I have double checked, and the drive letter "J:" is *NOT* in use when I run
this, yet the error seems to state the code thinks it is.

If I click the UnMap Drive I get an error telling me there is no such
resource in use, which I would expect, and until I can map a drive I can't
really test this one.

If I click the Get Drives button, I get an empty string back.

So now, it doesn't seem to be a permissions issue, but rather something
else.... but I have no clue what. Normally, typing in the error into Google
would get an answer in short order, but this error isn't helping much at
all.

Anyone have an idea as to what's happening here?

-- Andrew
 
A

Alex Clark

Andrew,

I may have completely misunderstood so forgive me in advance if so, but...

Was your ActiveX DLL executing on the client? If so, there's your problem.
The WebService code will be executing on the server, *not* the client. This
would explain why it worked when the web service was set up and installed on
your local computer for debugging, but failed when you copied it to your
server.

As for getting it to run on the client instead, there's a variety of
different .NET based client technologies, one of which is JScript.NET
(JavaScript which can interact with the Framework). I'm not sure how
suitable this would be as there are obvious security implications, but if
your intent is to execute code on the client side, then a web-service isn't
what you want to use.

HTH,
Alex
 
A

Andrew Raastad

Yeah, I knew I should've explained that a little better, or at least in more
detail. :)

We have this very large web-based application, which is written in something
called ObjectScript, the language for the database system named Caché, which
is distributed by InterSystems. This system however has the ability to
interact with COM/Active-X DLL's so that the ObjectScript application can
interact with the operating system... you could say it is analogous to
..Net's code behind, or the way you would use a Server.CreateObject(...) call
in old ASP. However, the version of Caché we are running does not "know
how" to talk directly with .Net Assemblies, just the old COM/Active-X DLL's.

The whole point of my project described previously is that we're trying to
expand our system to the 64-Bit servers, and the whole COM/Active-X method
of interaction is no longer supported there. So... I'm trying to come up
with a way that works on all servers, is using more modern code, and easiest
to maintain, thus the use of a Web Service since Caché understand SOAP
calls.

In short... forget Active-X or what it does, I simply mentioned it becuase
that was what the original DLL was written in. I am simply trying to get a
web service, residing on a server, called from another application on that
same or other server, to map a network drive on the server hosting the web
service so the application can make use of it. Nothing client-side, all
server-side.

-- Andrew
 
P

Patrice

Any reason for not using UNC path ? Drive mapping depends on the account and
if I remember when an account acts as a service you don't even have a user
profile loaded. How have you checked J: is not used ? You should try this
inside the web service.

That said, my personal preference by far would be not to used mapped drive
in a web application. A unc path is IMO much more manageable and is AFAIK a
much more common practice...
 
A

Andrew Raastad

I'd like to thank everyone who responded.... From those repsonses, here and
on other forums, articles I found or was pointed to, it all basically
pointed to the conclusion that attempting to do this via Web Services... not
a good idea. Just too many issues with permissions, user accounts, and so
forth, and it seems that this kind of thing was prevented by design to begin
with.

So, we solved the issue by creating a stand alone .exe that could receive
command line arguments. The application makes a shell call, passes the
arguments, and viola. Works pretty slick actually. But well, you never know
what will work in the end unless you go through the attempts in the
beginning. :)

-- Andrew
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top