Results 1 to 10 of 10

Thread: A way to determine environment

  1. #1

    Thread Starter
    PowerPoster Jenner's Avatar
    Join Date
    Jan 2008
    Location
    Mentor, OH
    Posts
    3,712

    A way to determine environment

    Good morning everyone,

    I have an odd problem I've been brainstorming over.
    I have a general purpose company application, that we want to install on some of the laptops the sales guys use. The problem is, some functions/modules of this application assumes it's running on a machine internal to our network and do things like access the Active Directory, access fileshares, etc.

    These laptops are "on the domain", and in a pinch can be connected via VPN, but I'm looking to make it more "mobile friendly" and write a system so it can access various data via a proxy server.

    I'm trying to figure out a good way for the app to "know" it's running on a computer that is currently on a network outside one of our buildings so it can do some things a bit differently.

    I considered looking for a file on an internal webserver or fileshare, but don't want to have to wait for a lengthy timeout since this check would be done every time the app is launched. It just didn't seem an "elegant" solution to me. Does anyone know if there's a way to check if a computer is currently attached to a specific domain-controlled network, either wired or wirelessly?

    Has anyone had to do anything similar? What did you do?

    Thanks in advance for any ideas
    My CodeBank Submissions: TETRIS using VB.NET2010 and XNA4.0, Strong Encryption Class, Hardware ID Information Class, Generic .NET Data Provider Class, Lambda Function Example, Lat/Long to UTM Conversion Class, Audio Class using BASS.DLL

    Remember to RATE the people who helped you and mark your forum RESOLVED when you're done!

    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. "
    - Albert Einstein

  2. #2
    Superbly Moderated NeedSomeAnswers's Avatar
    Join Date
    Jun 2002
    Location
    Manchester uk
    Posts
    2,660

    Re: A way to determine environment

    you could maybe try pinging the host -

    Code:
    string hostname = "<hostname>";
    
    Ping netping = new Ping();
    PingResponse response = netping.PingHost(hostname, 4);
    if (response != null)
    {
        ProcessResponse(response);
    }
    Please Mark your Thread "Resolved", if the query is solved & Rate those who have helped you



  3. #3
    Still learning kebo's Avatar
    Join Date
    Apr 2004
    Location
    Gardnerville,nv
    Posts
    3,758

    Re: A way to determine environment

    Try using System.DirectoryServices.ActiveDirectory.Domain.GetComputerDomain()

    The code is in c#, but you should get the gist..
    c#.net Code:
    1. static void Main(string[] args).
    2.         {
    3.             try
    4.             {
    5.                 System.DirectoryServices.ActiveDirectory.Domain domain = System.DirectoryServices.ActiveDirectory.Domain.GetComputerDomain();
    6.                 string domainName = domain.Name;
    7.                 Console.WriteLine("You are on " + domainName);
    8.             }
    9.             catch (Exception)
    10.             {
    11.  
    12.                 Console.WriteLine("You are not on a domain");
    13.             }  
    14.         }
    Tested for both being on a domain and not on a domain.
    Process control doesn't give you good quality, it gives you consistent quality.
    Good quality comes from consistently doing the right things.

    Vague general questions have vague general answers.
    A $100 donation is required for me to help you if you PM me asking for help. Instructions for donating to one of our local charities will be provided.

    ______________________________
    Last edited by kebo : Now. Reason: superfluous typo's

  4. #4

    Thread Starter
    PowerPoster Jenner's Avatar
    Join Date
    Jan 2008
    Location
    Mentor, OH
    Posts
    3,712

    Re: A way to determine environment

    @kebo: Would that work if the computer has "been joined to a domain" but "not on a domain controlled network" such as a home network or a hotel's? This is my problem. All these machines are "joined" to a domain. I need to know when they're "not on the internal network".

    @NeedSomeAnswers: I thought about that too, to just ping an internal server and see if I get a response. This was the route I was planning to go with if I didn't hear a more elegant solution on here. The only problem I have with it is I have a launcher program as well with an upgrade routine that looks for new versions of the application and if it finds one, informs the user, and download and installs it. Right now, it's grabbing it from a fileshare, which works great if on the internal network, but stinks if outside on the VPN. I thought about having it change to an FTP based routine for this. Maybe I should just convert the whole system to something that FTP based all the time, internal and external, or completely change my upgrade system. Seems like a huge headache though.
    My CodeBank Submissions: TETRIS using VB.NET2010 and XNA4.0, Strong Encryption Class, Hardware ID Information Class, Generic .NET Data Provider Class, Lambda Function Example, Lat/Long to UTM Conversion Class, Audio Class using BASS.DLL

    Remember to RATE the people who helped you and mark your forum RESOLVED when you're done!

    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. "
    - Albert Einstein

  5. #5
    Still learning kebo's Avatar
    Join Date
    Apr 2004
    Location
    Gardnerville,nv
    Posts
    3,758

    Re: A way to determine environment

    When I tested I did so on a domain and got the domain back. I also tested here at my home where I'm on a network, but not on a domain and it threw an exception. Either way, if you are looking to see if the machine is connected to a specific domain, I suppose you could test the domain name if the exception isn't raised.
    Last edited by kebo; Oct 30th, 2017 at 09:31 AM.
    Process control doesn't give you good quality, it gives you consistent quality.
    Good quality comes from consistently doing the right things.

    Vague general questions have vague general answers.
    A $100 donation is required for me to help you if you PM me asking for help. Instructions for donating to one of our local charities will be provided.

    ______________________________
    Last edited by kebo : Now. Reason: superfluous typo's

  6. #6
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,043

    Re: A way to determine environment

    How rapidly into the use of the application do you need to know? The point behind the question is that you have more options if you don't need to access some domain specific resource during startup, but only need it later on. If you have a bit of time, you could do the test on a secondary thread, in which case it really wouldn't matter too much how long it took (within reason). Of course, if the startup sequence is different depending on the domain, then a secondary thread buys you nothing.
    My usual boring signature: Nothing

  7. #7
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: A way to determine environment

    Probably the best thing to do is to try and access some server that can only be reached within the network.

    Keep in mind auto-detection always needs a safety hatch: suppose a user has an unplugged network cable or wifi was off. It's always friendly to have somewhere in your Options that lets the user toggle the switch back on if, for some reason, auto-detect has a bug.

    You don't have to wait a long time for things to time out. Most network APIs have support for specifying timeouts. If they don't, there's lots of ways to implement it yourself.

    For example, Ping.Send() has an overload that accepts a timeout value. Odds are if it takes longer than 2s to ping a "local" server, it's not reachable. You may find a 1s timeout fits even better. That's your judgement call. If you use this overload and the timeout is exceeded, the PingReply you get will have the Status property set to IPStatus.TimedOut.

    Now let's say you go a little less elegant route and want to look for some file/folder on the network. File.Exists() might work. But there's no asynchronous version, and that means it doesn't support a timeout. I know firsthand network file calls can have LONG timeouts. But I'd be willing to bet it's like pinging: if it takes much longer than 2s it's probably not succeeding at all.

    You can convert any synchronous operation to an asynchronous one quite easily. The Task API is a little clunky, but was designed for this. There's a well-established pattern for supporting a timeout (that is also sort of clunky). The idea is you start two different tasks: one 'does the thing' and the other 'is the timeout'. Then you wait on both of them. If the 'does the thing' task finishes first, you didn't time out. If the 'timeout' task finishes first, you timed out:
    Code:
    Imports System.IO
    
    Public Class Form1
        Private Async Sub Form1_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
    
            ' ... Display a splash screen or something.
    
            Dim isOnNetwork As Boolean = False
            Try
                Dim fileExists = Await DetectFileWithTimeoutAsync(TimeSpan.FromSeconds(2))
                isOnNetwork = fileExists
            Catch ex As Exception
                isOnNetwork = False
            End Try
    
            ' The rest of your load code goes here, it will execute on the UI thread.
        End Sub
    
        Public Function DetectFileWithTimeoutAsync(ByVal timeout As TimeSpan) As Task(Of Boolean)
            Return Task.Run(Function() DetectFileWithTimeout(timeout))
        End Function
    
        Private Function DetectFileWithTimeout(ByVal timeout As TimeSpan) As Boolean
            Dim filePath As String = "\\whatever\file"
    
            Dim findFileTask = Task.Run(Of Boolean)(Function()
                                                        Return File.Exists(filePath)
                                                    End Function)
            Dim timeoutTask = Task.Delay(timeout)
    
            Dim finishedIndex = Task.WaitAny(findFileTask, timeoutTask)
    
            If finishedIndex = 0 Then
                If findFileTask.Exception IsNot Nothing Then
                    ' Probably log this!
                    Return False
                Else
                    Return findFileTask.Result
                End If
            Else
                Throw New TimeoutException("Did not find the file in time.")
            End If
        End Function
    
    End Class
    This is a lot less clunky with the Reactive Extensions, for that you need to import some NuGet packages and learn a bit about Reactive programming though :/
    Code:
    Imports System.IO
    Imports System.Reactive.Concurrency
    Imports System.Reactive.Disposables
    Imports System.Reactive.Linq
    
    Public Class Form1
    
        Private _isOnNetwork As Boolean
    
        Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
    
            ' ... Display a splash screen or something.
    
            DetectFileAsync().Timeout(TimeSpan.FromSeconds(2)) _
                .ObserveOn(CurrentThreadScheduler.Instance) _
                .Subscribe(
                    Sub(success) FinishLoading(success),
                    Sub(ex) FinishLoading(False)
                )
        End Sub
    
        Private Sub FinishLoading(ByVal onNetwork As Boolean)
            ' This will be called on the UI thread, finish loading here.
        End Sub
    
        Public Function DetectFileAsync() As IObservable(Of Boolean)
            Return Observable.Create(Of Boolean)(Function(o)
                                                     Try
                                                         Dim fileExists = DetectFile()
                                                         o.OnNext(fileExists)
                                                     Catch ex As Exception
                                                         o.OnError(ex)
                                                     End Try
    
                                                     o.OnCompleted()
    
                                                     Return Disposable.Empty
                                                 End Function)
        End Function
    
        Private Function DetectFile() As Boolean
            Dim filePath As String = "\\whatever\file"
            Dim exists As Boolean = File.Exists(filePath)
            Return exists
        End Function
    
    End Class
    Both of these assume you need to know "right away", with respect to Shaggy Hiker's question. If you need to know "later", both can be adapted to raise an event or call some particular code when the answer becomes known.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  8. #8
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,043

    Re: A way to determine environment

    Yeah, that's the point behind my question: You have lots more options if you have the luxury of at least several seconds of time during startup before you need to know the answer to the question. I've done a few things kind of like this, but I always had the luxury of time.
    My usual boring signature: Nothing

  9. #9
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,600

    Re: A way to determine environment

    After reading this question a couple times, I realized what you're really asking for is a way to determine the fastest route and you should treat it as such. As someone who has a lot of experience in managing Windows networks, I can tell you that trying to determine if a particular machine is on a local network, domain or neither is not as clear cut as you might assume. Why ? It's because fundamentally, there is no such thing as a domain or network share. Nearly every network you're dealing with in your daily life is built on the TCP/IP protocol and this protocol is what all data transfers boil down to. TCP/IP only cares about end points. It's to get data from point A to point B. Domains, shared drives, workgroups etc are only abstractions meant to make the whole thing more manageable for humans. Even if you find a way to determine if a machine is connected to a domain controlled network it's never going to be 100% effective. A simple thing like an unplugged network cable or an improperly configured DHCP can lead to a lot of false positive and false negative results in your algorithms.

    Instead, I want you to completely abandon this idea of trying to determine what kind of network you're on. While there are times where it might be important, this is not one of them. The beating heart of what you really want to do is access remote data as quickly as possible. Look at the problem like that. If you have multiple ways to access the data based on if the machine in question is locally connected or outside, you should test once using both methods. If one fails and one succeeds, use the one that succeeds. If both methods succeed, use the one that gets the data faster. If both fail, inform the user that the data is inaccessible via an error message.

    If I were writing this application, I'd simply use Winsock. By using Winsock, you can get past all the messy abstractions like Domains and work groups and deal with this problem in it's purest form. All I want to know if if I can connect from machine A to machine B. Winsock doesn't make a distiction between remote machines and local network machines. Every machine is a remote machine as far as it's concerned so right there you avoid a lot of problems. You get a very easy one size fits all solution that is fast and elegant. The problem of where the local machine is can very easily be solved. If you can connect to your Server using a private IP address, then you're 100% certain you're on a local network, if you can only connect via a public IP, then you know for certain you're not on the local network. No need to check or domains and all that mess.

    Now you don't have to use Winsock. You can use abstractions like shared drives as long as you keep your concerns limited to whether you can reach the remote or not and how fast you can send/receive data.
    Last edited by Niya; Oct 30th, 2017 at 02:09 PM.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  10. #10
    Superbly Moderated NeedSomeAnswers's Avatar
    Join Date
    Jun 2002
    Location
    Manchester uk
    Posts
    2,660

    Re: A way to determine environment

    Your other option is to do your upgrade over a web service.

    If you have a hosted web service, it would be available the same internally and externally, you can use web service to download files and in fact its a common approach applications use to upgrade.

    The downside with this is you will need to host your web service somewhere which will likely have a cost associated with it, unless you have MSDN which comes with free Azure credits, and then you could spin up an Azure web server.
    Please Mark your Thread "Resolved", if the query is solved & Rate those who have helped you



Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width