Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Process.Start url with hidden WindowStyle

I have a url that authenticates my credentials on a server. Is there a way to make it invisible? The simple code looks exactly like this:

public void DoAuth()
    {
        String uri = GetUri();
        ProcessStartInfo startInfo = new ProcessStartInfo(uri);
        startInfo.WindowStyle = ProcessWindowStyle.Hidden;
        Process.Start(startInfo);

    }

however ProcessWindowStyle.Hidden doesn't seem to do the trick. If I set UseShellExecute to false then I get Win32Exception with the message The system cannot find the file specified The url is a authentication on Spotify server to get the playlists and it looks something like this https://accounts.spotify.com/authorize/client_id=26d287105as12315e12ds56e31491889f3cd293..

Is there an other way to make this process invisible?

Edit: http sample

public void DoAuth()
    {
        String uri = GetUri();

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
        HttpWebResponse webResponse;
        try
        {
            webResponse = (HttpWebResponse)request.GetResponse();
            Console.WriteLine("Error code: {0}", webResponse.StatusCode);
            using (Stream data = webResponse.GetResponseStream())
            using (var reader = new StreamReader(data))
            {
                //do what here?
            }
        }
        catch (Exception e)
        {
            throw;
        }
    }

The entire .cs file containing the sample above:

using SpotifyAPI.Web.Enums;
using SpotifyAPI.Web.Models;
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;

namespace SpotifyAPI.Web.Auth
{
    public class ImplicitGrantAuth
    {
        public delegate void OnResponseReceived(Token token, String state);

        private SimpleHttpServer _httpServer;
        private Thread _httpThread;
        public String ClientId { get; set; }
        public String RedirectUri { get; set; }
        public String State { get; set; }
        public Scope Scope { get; set; }
        public Boolean ShowDialog { get; set; }

        public event OnResponseReceived OnResponseReceivedEvent;

        /// <summary>
        ///     Start the auth process (Make sure the internal HTTP-Server ist started)
        /// </summary>
        public void DoAuth()
        {
            String uri = GetUri();

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
            HttpWebResponse webResponse;
            try
            {
                webResponse = (HttpWebResponse)request.GetResponse();
                Console.WriteLine("Error code: {0}", webResponse.StatusCode);
                using (Stream data = webResponse.GetResponseStream())
                using (var reader = new StreamReader(data))
                {
                    //nothing
                }
            }
            catch (Exception e)
            {
                throw;
            }


            /*ProcessStartInfo startInfo = new ProcessStartInfo(uri);
            startInfo.WindowStyle = ProcessWindowStyle.Hidden;
            Process.Start(startInfo);
            */
        }

        private String GetUri()
        {
            StringBuilder builder = new StringBuilder("https://accounts.spotify.com/authorize/?");
            builder.Append("client_id=" + ClientId);
            builder.Append("&response_type=token");
            builder.Append("&redirect_uri=" + RedirectUri);
            builder.Append("&state=" + State);
            builder.Append("&scope=" + Scope.GetStringAttribute(" "));
            builder.Append("&show_dialog=" + ShowDialog);
            return builder.ToString();
        }

        /// <summary>
        ///     Start the internal HTTP-Server
        /// </summary>
        public void StartHttpServer(int port = 80)
        {
            _httpServer = new SimpleHttpServer(port, AuthType.Implicit);
            _httpServer.OnAuth += HttpServerOnOnAuth;

            _httpThread = new Thread(_httpServer.Listen);
            _httpThread.Start();
        }

        private void HttpServerOnOnAuth(AuthEventArgs e)
        {
            OnResponseReceivedEvent?.Invoke(new Token
            {
                AccessToken = e.Code,
                TokenType = e.TokenType,
                ExpiresIn = e.ExpiresIn,
                Error = e.Error
            }, e.State);
        }

        /// <summary>
        ///     This will stop the internal HTTP-Server (Should be called after you got the Token)
        /// </summary>
        public void StopHttpServer()
        {
            _httpServer.Dispose();
            _httpServer = null;
        }
    }
}

And they are called like this:

_auth.OnResponseReceivedEvent += _auth_OnResponseReceivedEvent;
_auth.StartHttpServer(8000);
_auth.DoAuth();

The github url with a full runnable sampe is here: https://github.com/JohnnyCrazy/SpotifyAPI-NET Download it and run the Spotify Test to connect to Spotify's web api to reproduce the sample I have.

like image 810
John P. Avatar asked May 01 '16 01:05

John P.


2 Answers

The entrypoint of a GUI program on Windows is the famous WinMain() function. It looks like this:

  int CALLBACK WinMain(
    _In_ HINSTANCE hInstance,
    _In_ HINSTANCE hPrevInstance,
    _In_ LPSTR     lpCmdLine,
    _In_ int       nCmdShow
  );

The hInstance and hPrevInstance arguments are legacy and date back to Windows versions <= 3, versions that did not have support processes yet and required an app to take care of multiple instances of a task itself. The lpCmdLine argument are the command line arguments.

nCmdShow is the important one and the subject of your question. Expected values are SW_HIDE, SW_SHOWNORMAL, SW_SHOWMAXIMIZE or SW_SHOWMINIMIZE. You can easily map them yourself to the possible ProcessWindowStyle enum values.

It is also exposed in the properties of a shortcut on your desktop. For example:

enter image description here

I expanded the Run combobox, note the match with the ProcessWindowStyle enum values. Except Hidden, hint of trouble there.


A typical C program passes the nCmdShow argument directly to the ShowWindow() function to display the main window (error checking omitted):

   HWND hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
   ShowWindow(hWnd, nCmdShow);

You'd be happy with such a program. It is however not the way many programs actually work. They check the value of nCmdShow and explicitly filter out SW_HIDDEN. Or they restore the window state that the user last used. In other words, they do this:

   HWND hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
   if (nCmdShow == SW_HIDDEN) nCmdShow = SW_SHOWNORMAL;
   if (HasPreviousWindowState) nCmdShow = PreviousWindowState;   // optional
   ShowWindow(hWnd, nCmdShow);

This is for a done for good reasons. Restoring the previous state is an obvious usability preference, many users will prefer it works that way for a browser for example. I do.

More to the point for the missing Hidden option in the shortcut configuration dialog, both the OS and well-designed GUI programs intentionally avoid creating a usability nightmare. Where the program gets started but there is no way for the user to activate the program. There is no taskbar button for a hidden window. Alt+Tab does not work. The only way the user can regain control over the program is to terminate it with Task Manager. It is also exploitable, malware could start a program and commandeer it and the user never notices.

All good reasons why such a program prevents this from happening. Nothing you can do about it, the program overrides your choice and has the last say about it.

like image 103
Hans Passant Avatar answered Nov 03 '22 15:11

Hans Passant


Go into the project properties in Visual Studio and change your project type to Class Library. Save it. Then change it to Windows Application and save.

That should get rid of any UI you are not explicitly creating yourself.

like image 2
hoodaticus Avatar answered Nov 03 '22 14:11

hoodaticus