簡體   English   中英

使用隱藏的WindowStyle啟動Process.Start url

[英]Process.Start url with hidden WindowStyle

我有一個在服務器上驗證我的憑據的URL。 有沒有辦法讓它看不見? 簡單的代碼看起來完全像這樣:

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

    }

但是ProcessWindowStyle.Hidden似乎沒有做到這一點。 如果我將UseShellExecute設置為false然后我收到Win32Exception並顯示消息The system cannot find the file specified url是Spotify服務器上的身份驗證以獲取播放列表,它看起來像這樣https://accounts.spotify.com/authorize/client_id=26d287105as12315e12ds56e31491889f3cd293..

還有其他方法可以使這個過程不可見嗎?

編輯:http示例

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;
        }
    }

包含上述示例的整個.cs文件:

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;
        }
    }
}

它們被稱為這樣:

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

帶有完整可運行樣品的github url在這里: https//github.com/JohnnyCrazy/SpotifyAPI-NET下載並運行Spotify測試以連接Spotify的web api以重現我的樣本。

Windows上GUI程序的入口點是着名的WinMain()函數 它看起來像這樣:

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

hInstance和hPrevInstance參數是遺留的,並且可以追溯到Windows版本<= 3,尚未支持進程的版本,並且需要應用程序來處理任務本身的多個實例。 lpCmdLine參數是命令行參數。

nCmdShow是您的重要問題和主題。 預期值為SW_HIDE,SW_SHOWNORMAL,SW_SHOWMAXIMIZE或SW_SHOWMINIMIZE。 您可以輕松地將它們映射到可能的ProcessWindowStyle枚舉值。

它也暴露在桌面上的快捷方式屬性中。 例如:

在此輸入圖像描述

我展開了Run組合框,注意與ProcessWindowStyle枚舉值的匹配。 除了Hidden ,那里有一絲麻煩。


典型的C程序將nCmdShow參數直接傳遞給ShowWindow()函數以顯示主窗口(省略錯誤檢查):

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

你會對這樣的節目感到滿意。 然而,這並不是許多程序實際工作的方式。 他們檢查 nCmdShow的值並明確過濾掉SW_HIDDEN 或者他們恢復用戶上次使用的窗口狀態。 換句話說,他們這樣做:

   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);

這是有充分理由的。 恢復以前的狀態是一個明顯的可用性偏好,許多用戶會更喜歡它以這種方式為瀏覽器工作。 我做。

對於快捷方式配置對話框中缺少Hidden選項的更多信息,操作系統和精心設計的GUI程序都有意避免產生可用性噩夢。 程序啟動的地方,但用戶無法激活程序。 隱藏窗口沒有任務欄按鈕。 Alt + Tab不起作用。 用戶重新獲得對程序的控制權的唯一方法是使用任務管理器終止它。 它也是可利用的,惡意軟件可以啟動程序並征用它並且用戶從不會注意到它。

這樣一個程序阻止這種情況發生的所有好理由。 沒有什么可以做的,程序會覆蓋你的選擇並對此有最后的發言權。

進入Visual Studio中的項目屬性,並將項目類型更改為類庫。 保存。 然后將其更改為Windows應用程序並保存。

這應該擺脫你沒有明確創建自己的UI。

我認為你不需要開始一個新的流程來獲得Spoitfy的授權。 您應該進行Get / Post調用並獲取授權令牌,然后將其包含在您將來的API調用中。

GET https://accounts.spotify.com/authorize

我指的是Spoitfy的在線幫助頁面。

https://developer.spotify.com/web-api/authorization-guide/

經典XY問題,您沒有搜索隱藏窗口的方法, 您希望在沒有涉及用戶操作的情況下對用戶進行身份驗證

由於ImplicitGrantAuth不適用於簡單的HTTP請求,因此您需要一種解決方法:

無用戶操作進行身份驗證:無頭瀏覽器

雖然ImplicitGrantAuth不是為這種任務而制作的,但它仍然可能但不干凈。 你需要一個無頭瀏覽器,你可以在你的C#App中控制它,比如Selenium

考慮使用Selenium代碼( 相關SO問題 ):

void DoAuth()
{
    IWebDriver driver = new FirefoxDriver();

    driver.Navigate().GoToUrl(GetUri());
    IWebElement query = driver.FindElement(By.Name("username")); //You need to search for the correct element
    query.SendKeys("username");
    query = driver.FineElement(By.Name("password"));
    query.SendKeys("password");

    //Somehow submit the form and wait till you get the Token via URL
    //Thread.Sleep(5000);
    String urlWithToken = driver.Url;

    //Analyze it and get the token out of it

    driver.Quit();
}

這只是偽正確的代碼,但你應該明白這個想法。 使用您可以控制的無頭瀏覽器,填寫所有表單輸入,提交和分析URL。 Facebook登錄將是相同的原則。

但是請注意: OAuth不是為這種類型的使用而設計的,並且您可能不應該在生產中使用這種hacky變通方法

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM