0

I have an app that i have built, and i have placed it on a share drive on a server in order to distribute it to other users. However, i want the application to check where it is being launched, and if it is being launched directly on the share, popup a message that says something like this: "The application cannot run from this location. Would you like to install it on your local computer instead?"

The problem I am having is the following: because the user is launching it by browsing to the share, the CurrentDomain within the app is relative to how the user browsed to the share. Therefore, it is basically impossible to (this is my question:) determine if the application is being launched on the server!

If the user is browsing to the share manually by typing:
\\SERVER\SharedFolder\App\MyApp.exe
then the executing assemly always returns the UNC share (\...)...

If the user however, is remoting into the server, the path would be this one:
D:\Shares\MyAppSharedFolder\Loader\MyApp.exe

If the user however, has the SharedFolder mapped to his local drive Z:
Z:\App\MyApp.exe
Then the returned value is the Z:\ value.

So my question is: is there an easy way to always get the same value back, regardless of how the user browsed to the app after it has launched?

i tried this solution:
http://briancaos.wordpress.com/2009/03/05/get-local-path-from-unc-path/
But that ONLY works if the path is of UNC Share Format (\ ...)

So what is the proper way of getting the .exe that is running's TRUE local path, wherever it is being run or how it was browsed to?

Kara
  • 6,115
  • 16
  • 50
  • 57
MaxOvrdrv
  • 1,780
  • 17
  • 32
  • possible duplicate of [How can I determine if a given drive letter is a local/mapped/usb drive?](http://stackoverflow.com/questions/4396634/how-can-i-determine-if-a-given-drive-letter-is-a-local-mapped-usb-drive). The root of the question is, is the drive local or not, the reasons for which are ancillary. – Erik Philips Aug 28 '14 at 18:45
  • @ErikPhilips I disagree... I want to get the Executing Assembly's LOCAL path, regardless of the User Domain its running on, or how he/she browsed to it... If the answer to that is "You can't and have to account for all scenarios", then I would use that answer to help me build that (much bigger) piece of code, but is there a way to get the Local/Actual assembly path easily in another way? – MaxOvrdrv Aug 28 '14 at 18:46
  • Then are you asking how you get the [Assembly.GetExecutingAssembly()](http://msdn.microsoft.com/en-us/library/system.reflection.assembly.getexecutingassembly(v=vs.110).aspx) executing [Location](http://msdn.microsoft.com/en-us/library/system.reflection.assembly.location(v=vs.110).aspx)? I also don't know what `User Domain` means, and know how the application was executed is useless to the root question (because if I create a shortcut on my desktop, that is where browsed to, to start the application, but now where it's executed from). – Erik Philips Aug 28 '14 at 18:48
  • yes, but the actual one local to the server... i am using that code bit right now and for example: if i run my app and msgbox the result of that code, and i browse to it using a \\ path in explorer, i get the \\ path back, if i run it from my mapped location to Z:, i get the Z: back... is there something that would give the me actual path of where it truly lies on the server like D:\ ... ? – MaxOvrdrv Aug 28 '14 at 18:53
  • The first comment I made will tell you if it's a local drive or not. *ALL* UNC paths are by definition remote and will use the network stack to execute even if the share is on the local device. – Erik Philips Aug 28 '14 at 18:55
  • that's exactly what User Domain means i guess... that i don't want the "shortcut you clicked" location, but the actual .exe's location that is running? – MaxOvrdrv Aug 28 '14 at 18:55
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/60187/discussion-between-erik-philips-and-maxovrdrv). – Erik Philips Aug 28 '14 at 18:55

1 Answers1

0

Ok, so here's what i ended up doing... and no, this question did not have an answer/is not a duplicate.

In short, the answer to my question is this:
It can't be done/there is no easy and built-in way to know where the application is TRULY being run without taking into account the "User Domain/Profile/Context".

Therefore, a more complex and comprehensive solution had to be implemented in the following manner (pseudo-coded):


Make RunLocation = GetEntryAssembly!

IF RunLocation == ServerLocationAsUNC OR LocalServerLocation
{
//so here, if the location is \\SERVER\SharedFolder\App\ OR D:\Shares\MyAppSharedFolder\Loader\
    PROMPT FOR INSTALL LOCATION/DO NOT RUN!
}
ELSE
{
    IF RunLocation Starts With a "\\"
    { 
        Extract the Server name from RunLocation
        Get the IP Address of that server

        IF RunLocationIP == KnownServerIP
        {
            PROMPT FOR INSTALL LOCATION/DO NOT RUN!
        }
        ELSE
        {
            ALLOW TO RUN!
        }
    }
    ELSE (if RunLocation does NOT start with a "\\")
    {
        Get the DriveInfo for RunLocation (example: "E:\")
        IF the DriveInfo is NOT a Network Location
        {
            ALLOW TO RUN!
        }
        ELSE
        {
            Using ManagementObject, Get the UNC path for that DriveInfo
            Extract the Server name from UNCPath
            Get the IP Address of that server

             IF DriveLocationIP == KnownServerIP
             {
                 PROMPT FOR INSTALL LOCATION/DO NOT RUN!
             }
             ELSE
             {
                 ALLOW TO RUN!
             }
        }
    }
}

so that's the Pseudo-Code version...

Here's the actual method i ended up building to check for this and use it everywhere i needed it... keep in mind that this is not flawless (for example, if the local PC has the same expected Local Server Path and that is chosen, it will prompt for an install location when it shouldn't, which i really don't mind myself), and it is built for my needs so i have some extra checks in there (like, cannot be the Desktop) that you may not need... but regardless, here's the actual coded version.

    private enum I_Am
    {
        OnTheServer,
        OnTheLocalPC
    }

    /// <summary>
    /// This method returns whether or not the application is being run at an appropriate location.
    /// </summary>
    /// <returns>Enum I_Am - Either: I_Am.OnTheServer OR I_Am.OnTheLocalPC</returns>
    private I_Am CheckLocation()
    {
        //decalre local vars...
        string bs = Path.DirectorySeparatorChar.ToString();
        string dbs = bs +bs;
        string dir = MyBaseDir;
        I_Am retval = I_Am.OnTheServer;

        //if run location is the UNC Share Server Path OR the Expected Local Server Path, or the Desktop or at the Root of a drive
        //consider this a server/invalid run location.
        if (dir == ServerBaseDir ||
            dir == LocalServerBaseDir ||
            dir == DesktopDir ||
            IsRootDrive(dir))
        {
            retval = I_Am.OnTheServer;
        }
        else
        {
            //if the location is a UNC path entered by the user (e.g.: "\\ServerName")
            if (dir.StartsWith(dbs))
            {
                //extract the server name from the path
                dir = dir.Remove(0, 2);
                List<string> parts = dir.Split(new string[] { bs }, StringSplitOptions.None).ToList();
                string servername = parts[0];
                //get the list of possible IP addresses for that server
                System.Net.IPHostEntry server = System.Net.Dns.GetHostEntry(servername);
                //if that list of IPs contains our distribution server, consider this a server/invalid run location.
                //else, all good/allow to run!
                if (server.AddressList.Contains(System.Net.IPAddress.Parse(ServerIP)))
                    retval = I_Am.OnTheServer;
                else
                    retval = I_Am.OnTheLocalPC;

            }
            else
            {
                //if this is a local drive, it could be mapped to a share/network location which we must check)

                //get the drive info for the drive...
                DriveInfo drive = new DriveInfo(dir[0].ToString());
                //if it's NOT a network drive, all good/allow to run!
                if (drive.DriveType != DriveType.Network)
                {
                    return I_Am.OnTheLocalPC;
                }
                else
                {
                    //if this is a network drive, we now have to check the UNC to IP mapping again...

                    //get the UNC path from the ManagementObject...
                    ManagementObject mo = new ManagementObject();
                    mo.Path = new ManagementPath(string.Format("Win32_LogicalDisk='{0}'", drive.Name));
                    dir = Convert.ToString(mo["ProviderName"]);

                    //extract the server name from the path
                    dir = dir.Remove(0, 2);
                    List<string> parts = dir.Split(new string[] { bs }, StringSplitOptions.None).ToList();
                    string servername = parts[0];
                    //get the list of possible IP addresses for that server
                    System.Net.IPHostEntry server = System.Net.Dns.GetHostEntry(servername);
                    //if that list of IPs contains our distribution server, consider this a server/invalid run location.
                    //else, all good/allow to run!
                    if (server.AddressList.Contains(System.Net.IPAddress.Parse(ServerIP)))
                        retval = I_Am.OnTheServer;
                    else
                        retval = I_Am.OnTheLocalPC;
                }
            }
        }

        return retval;
    }
MaxOvrdrv
  • 1,780
  • 17
  • 32