none
C# call to WNetEnumResource stopped working in Windows 10.0.10586 and newer RRS feed

  • Question

  • We develop client server software in C# and use WNetEnumResource() to get a list of computers on the network for users to select from as their "server". Since the Windows 10.0.10586 update to Windows, this function has stopped returning results.
    All computers that are not running this version of Windows still functions normally and will see a list of computers. This list is not limited to Domain joined computers, it sees all active computers on the network. 

    There is little information about this specific issue when performing searches.
    What I do find when researching getting a list of computers on the network is the method we are using which is to pinvoke WNetEnumResource.

    Another suggestion seen often is to query DirectoryServices. Following examples on this have provided varying results. Most example result in zero results while other more pointed examples do return results, but only explicitly for that computers workgroup/domain and not the network. These pointed results can be much larger result sets than active computers on the network as they are getting a list of all computer objects from the domain even if they are not active on the network or subnet.

    So, with Windows 10 breaking the pinvoke to WNetEnumResource, how do we query a list of active computers on the network quickly and efficiently?

    Thanks for all who can actually help!


    • Edited by Ben.Stine Wednesday, January 13, 2016 12:34 PM
    Wednesday, January 13, 2016 12:33 PM

All replies

  • What do you mean that the PInvoke to WNetEnumResource fails?  Are you seeing it succeed and just find nothing?

    I was able to run this function successfully on my 10586 laptop:

        class Program
        {
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
            struct NETRESOURCE
            {
                public int Scope;
                public int Type;
                public int DisplayType;
                public int Usage;
                public string LocalName;
                public string RemoteName;
                public string Comment;
                public string Provider;
            }
            [DllImport("Mpr", CharSet = CharSet.Unicode)]
            static extern int WNetOpenEnum(int scope, int type, int usage, IntPtr netResource, out IntPtr handle);
            [DllImport("Mpr", CharSet = CharSet.Unicode)]
            static extern int WNetEnumResource(IntPtr handle, ref int count, IntPtr buffer, ref int bufferSize);
            [DllImport("Mpr", CharSet = CharSet.Unicode)]
            static extern int WNetCloseEnum(IntPtr handle);
            const int RESOURCE_CONNECTED = 0x00000001;
            const int RESOURCE_GLOBALNET = 0x00000002;
            const int RESOURCE_REMEMBERED = 0x00000003;
            const int RESOURCE_RECENT = 0x00000004;
            const int RESOURCE_CONTEXT = 0x00000005;
            const int RESOURCETYPE_ANY = 0x00000000;
            const int RESOURCETYPE_DISK = 0x00000001;
            const int RESOURCETYPE_PRINT = 0x00000002;
            static int HRESULT_FROM_WIN32(int error)
            {
                return error <= 0 ? error : (int)((error & 0x0000FFFF) | (7 << 16) | unchecked((int)0x80000000)); 
            }
            static void EnumResources(IntPtr nr)
            {
                IntPtr handle;
                int result = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_ANY, 0, nr, out handle);
                if (result == 0)
                {
                    IntPtr buffer = Marshal.AllocHGlobal(50000);
                    try
                    {
                        while (true)
                        {
                            int bufferSize = 50000;
                            int count = -1;
                            result = WNetEnumResource(handle, ref count, buffer, ref bufferSize);
                            if (result == 0)
                            {
                                for (int i = 0; i < count; i++)
                                {
                                    IntPtr tmp = IntPtr.Add(buffer, i * Marshal.SizeOf(typeof(NETRESOURCE)));
                                    NETRESOURCE nr2 = Marshal.PtrToStructure<NETRESOURCE>(tmp);
                                    Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}", nr2.Scope, nr2.Type, nr2.DisplayType, nr2.Usage & 0xFFFFFFF, nr2.LocalName, nr2.RemoteName, nr2.Provider, nr2.Comment);
                                    if(nr2.Scope == RESOURCE_GLOBALNET && (nr2.Usage & 2) == 2)
                                    {
                                        EnumResources(tmp);
                                    }
                                }
                            }
                            else
                            {
                                Console.WriteLine("Error result:\t{0}-{1}", result, Marshal.GetExceptionForHR(HRESULT_FROM_WIN32(result)));
                                break;
                            }
                        }
                    }
                    finally
                    {
                        Marshal.FreeHGlobal(buffer);
                        WNetCloseEnum(handle);
                    }
                }
                else
                {
                    Console.WriteLine("Error result:\t{0}-{1}", result, Marshal.GetExceptionForHR(HRESULT_FROM_WIN32(result)));
                }
            }
            static void Main(string[] args)
            {
                EnumResources(IntPtr.Zero);
    
            }
        }

    If I disable the Browser service, it will fail to find any computers; if no browsers are running on the subnet and it's not disabled (but set not to be the list keeper for the subnet), it also doesn't find any computers.  Is it disabled when you're testing?


    WinSDK Support Team Blog: http://blogs.msdn.com/b/winsdk/

    Wednesday, January 13, 2016 10:45 PM
  • Hello and thank you for responding.

    The Computer Browser is disabled on non-domain controllers by domain group policy. The PDC has the Computer Browser service running and is the master browser server.

    I copied your code into a Console application to quickly run on every OS we run in the building.

    On Windows 10.0.10586, when your code runs, there are 3 entries (Microsoft Terminal Services, Microsoft Windows Network, Web Client Network)
    None of these have any sub entries.

    In all other versions of Windows the Computer Browser is not turned on (Domain Group Policy) and this code returns the list of expected computers.

    In Windows 10.0.10586 in testing I have turned on the Computer Browser service (as you suggested) and run the program. I do see a change and this is where this version of Windows is "broken".
    The difference with the Computer Browser service running is that under the Microsoft Windows Network, there are now a few entries.
    The first entry is for the domain name (ALLMAX). The second entry is my computer name \\IP54BEN. Lastly is \\IP54BEN\Users. The expected list of computers is not shown, not even the Master Browser (the PDC).

    This is the only change from turning on the Computer Browser service.

    With the same setup in Windows XP - Windows 10.0.10240 (Computer Browser service off)
    Run this code and the list of computers is shown as expected (multiple Microsoft Windows Networks and sub entries).
    Update any of the Windows 10 to 10.0.10586 and this list is now empty. That is why I say it stopped working (broken).
    It is the only version to run deviant behavior.

    Information or suggestions would be appreciated. 

    *Note:

    The Microsoft Windows Network has multiple networks showing in the expected list.
    First to show is our Domain: ALLMAX, then ELEVTRO and finally WORKGROUP

    Trying to establish a list of computers by using the DirectoryEntries has failed for our attempts to quickly and concisely present a similar list of computers. Directory Entries will produce a list of all the Computer objects listed in the DOMAIN, which is not what WNetEnumResource provides.

    Thursday, January 14, 2016 12:27 PM
  • Thanks for all the info.  Since you don't have browser running in your other scenarios, you're wanting information from a provider other than the Browser (which WNetEnumResource uses via NetServerEnum for that provider). 

    Do you see the list that you want when you type in Network to the browser bar in explorer?


    WinSDK Support Team Blog: http://blogs.msdn.com/b/winsdk/

    Thursday, January 14, 2016 8:03 PM
  • Your last question about seeing the list in Explorer for the network, the answer is no, this has also been broken with the release of Windows 10.0.10586 which has many user complaints in the Feedback app. 

    Only the computers running Windows 10.0.10586 no longer can see all the network computers, they all see a small subset. All other computers on our network running Windows 10.0.10240 and older can see all the computers on the network. 

    A note about our Domain controllers, they are all Windows Server Standard 2008 R2.

    What I am uncertain of is: Was there a bug in all OSes before 10.0.10586 where WNetEnumResource would active the Browser service to obtain the list and then shut it off and Windows 10.0.10586 fixed this bug.
    Or did Windows 10.0.10586 break some sort of functionality to this call since all other OSes see the list of computers just fine with the Browser service disabled? Such as not querying the Master Browser either when the Browser service is enable or disabled? 

    The issue with not seeing the full list of computers in Explorer is not resolved when the Browser service is turned on. This list remains the same.

    Through some experimenting I have found only one solution to get my computer to see the list as it use to before the update to 10.0.10586.
    That is to turn off every Computer Browser service from every computer, server or device. Then enable and turn on the service for my computer. This essentially has my computer running as the Master browser. Only in this scenario will the list populate correctly. This does not resolve the issue for any other computer running on the network, only mine.

    Any other computer running 10.0.10586 for 2 scenarios here.
    First, without the Browser service running: The call to WNetEnumResource does not return the list properly, nor does Explorer show the proper list of computers.

    Second, with the Browser service running. The call to WNetEnumResource returns only their computer name and no other computers. (appears to be a master browser conflict). Yet, Explorer appears to get a subset list of computers from the Master browser (my computer), but not the full list.

    I hope this additional information is helpful in understanding our frustration with Windows 10.0.10586 and can help us either get a fix for Windows 10.0.10586 or point us to a solution that works with 10.0.10586 as well as every other OS that has not been broken for this call.

    It seems silly to have code that explicitly looks for this version of Windows 10 to provide an alternate method for providing a list of computers. Not when this functionality works in 10.0.10240. What it does it make us not want to update our computers running 10.0.10240 until the network issues are resolved with 10.0.10586.

    Thursday, January 14, 2016 8:36 PM
  • Thanks for the information and the feedback.  I can certainly understand the frustration.  The goal of my questions has been to help narrow down which provider isn't working in 10586.  There haven't been any code changes in WNetEnumResource in nearly four years, so the behavioral difference you're seeing is in something downstream.  Not sure when it will be, but I'll try to track down where in the providers the behavior change is occurs and submit a bug on it internally assuming I find a defect (which seems likely). 

    WinSDK Support Team Blog: http://blogs.msdn.com/b/winsdk/

    Thursday, January 14, 2016 9:07 PM
  • A year ago I built a little utility that used several methods for obtaining network computers.
    Another bit of code that stopped working in 10.0.10586 is:
    using (DirectoryEntry root = new DirectoryEntry("WinNT:"))
    {
    	var domainNames = (from DirectoryEntry domains in root.Children
    					 select domains.Name).ToList();
    
    	if (domainNames != null)
    	{
    		foreach (String str in domainNames)
    			DomainNameList.Add(str);
    	}
    }
    This code use to list the different network names that was seen in the WNetEnumResource calls.
    The little utility called WNetEnumResource as well as used the above code block to get the network names to supply NetServerEnum
    We were comparing speeds and return results for both methods.

    The WNetEnumResource method was more complete but it did add a bit of time if there were resources that it did not have permissions to access.
    Thursday, January 14, 2016 9:16 PM
  • @Ben,

    Try report using the Feedback app in Windows 10. Please also add your repro demo.


    • Edited by Linki Tan Monday, January 18, 2016 9:28 AM
    Monday, January 18, 2016 9:28 AM
  • Hi Ben,

    Did you get any fix for this issue ?

    We are facing the same issue in windows 2008 R2 system (With WNetEnumResource api not getting the list of computers) , it used to work fine. We are suspecting that one of the recent windows updates might be causing the issue. Please let me know.

    Thanks, 

     Syam

    WNetEnumResource

    WNetEnumResource

    Thursday, February 11, 2016 10:52 PM
  • No fix has come through Windows update and no other fix has been found on our end.
    Friday, February 12, 2016 1:41 PM