سؤال

أنا أكتب خادم HTTP في C#.

عندما أحاول تنفيذ الوظيفة HttpListener.Start() أحصل على HttpListenerException القول

"تم الرفض".

عندما أقوم بتشغيل التطبيق في وضع المسؤول في Windows 7 ، يعمل بشكل جيد.

هل يمكنني تشغيله بدون وضع المسؤول؟ إذا كانت الإجابة بنعم كيف؟ إن لم يكن كيف يمكنني تغيير التطبيق إلى وضع المسؤول بعد بدء التشغيل؟

using System;
using System.Net;

namespace ConsoleApplication1
{
    class Program
    {
        private HttpListener httpListener = null;

        static void Main(string[] args)
        {
            Program p = new Program();
            p.Server();
        }

        public void Server()
        {
            this.httpListener = new HttpListener();

            if (httpListener.IsListening)
                throw new InvalidOperationException("Server is currently running.");

            httpListener.Prefixes.Clear();
            httpListener.Prefixes.Add("http://*:4444/");

            try
            {
                httpListener.Start(); //Throws Exception
            }
            catch (HttpListenerException ex)
            {
                if (ex.Message.Contains("Access is denied"))
                {
                    return;
                }
                else
                {
                    throw;
                }
            }
        }
    }
}
هل كانت مفيدة؟

المحلول

نعم ، يمكنك تشغيل httplistener في وضع غير Radmin. كل ما عليك فعله هو منح أذونات لعنوان URL معين. على سبيل المثال

netsh http add urlacl url=http://+:80/MyUri user=DOMAIN\user

الوثائق هنا.

نصائح أخرى

هل يمكنني تشغيله بدون وضع المسؤول؟ إذا كانت الإجابة بنعم كيف؟ إن لم يكن كيف يمكنني تغيير التطبيق إلى وضع المسؤول بعد بدء التشغيل؟

لا يمكنك ذلك ، يجب أن تبدأ بامتيازات مرتفعة. يمكنك إعادة تشغيله باستخدام runas الفعل ، الذي سيطالب المستخدم بالتبديل إلى وضع المسؤول

static void RestartAsAdmin()
{
    var startInfo = new ProcessStartInfo("yourApp.exe") { Verb = "runas" };
    Process.Start(startInfo);
    Environment.Exit(0);
}

تحرير: في الواقع ، هذا ليس صحيحًا ؛ يمكن أن يعمل HttPlistener دون امتيازات مرتفعة ، ولكن عليك أن تقدم إذنًا بعنوان URL الذي تريد الاستماع إليه. نرى إجابة داريل ميلر للتفاصيل.

كما ترى http://localhost:80/ كبادئة ، يمكنك الاستماع إلى طلبات HTTP دون الحاجة إلى امتيازات إدارية.

كان بناء الجملة خاطئًا بالنسبة لي ، يجب أن تتضمن عروض الأسعار:

netsh http add urlacl url="http://+:4200/" user=everyone

وإلا فقد تلقيت "المعلمة غير صحيحة"

في حال كنت ترغب في استخدام العلامة "user = elope" ، فأنت بحاجة إلى ضبطها على لغة النظام الخاصة بك. باللغة الإنجليزية كما ذكر:

netsh http add urlacl url=http://+:80/ user=Everyone

في الألمانية سيكون:

netsh http add urlacl url=http://+:80/ user=Jeder

كبديل لا يتطلب الارتفاع أو netsh ، يمكنك أيضًا استخدام TCPlistener على سبيل المثال.

فيما يلي مقتطفات معدلة لهذه العينة:https://github.com/googlesamples/oauth-apps-for-windows/tree/master/oauthdesktopapp

// Generates state and PKCE values.
string state = randomDataBase64url(32);
string code_verifier = randomDataBase64url(32);
string code_challenge = base64urlencodeNoPadding(sha256(code_verifier));
const string code_challenge_method = "S256";

// Creates a redirect URI using an available port on the loopback address.
var listener = new TcpListener(IPAddress.Loopback, 0);
listener.Start();
string redirectURI = string.Format("http://{0}:{1}/", IPAddress.Loopback, ((IPEndPoint)listener.LocalEndpoint).Port);
output("redirect URI: " + redirectURI);

// Creates the OAuth 2.0 authorization request.
string authorizationRequest = string.Format("{0}?response_type=code&scope=openid%20profile&redirect_uri={1}&client_id={2}&state={3}&code_challenge={4}&code_challenge_method={5}",
    authorizationEndpoint,
    System.Uri.EscapeDataString(redirectURI),
    clientID,
    state,
    code_challenge,
    code_challenge_method);

// Opens request in the browser.
System.Diagnostics.Process.Start(authorizationRequest);

// Waits for the OAuth authorization response.
var client = await listener.AcceptTcpClientAsync();

// Read response.
var response = ReadString(client);

// Brings this app back to the foreground.
this.Activate();

// Sends an HTTP response to the browser.
WriteStringAsync(client, "<html><head><meta http-equiv='refresh' content='10;url=https://google.com'></head><body>Please close this window and return to the app.</body></html>").ContinueWith(t =>
{
    client.Dispose();
    listener.Stop();

    Console.WriteLine("HTTP server stopped.");
});

// TODO: Check the response here to get the authorization code and verify the code challenge

طرق القراءة والكتابة هي:

private string ReadString(TcpClient client)
{
    var readBuffer = new byte[client.ReceiveBufferSize];
    string fullServerReply = null;

    using (var inStream = new MemoryStream())
    {
        var stream = client.GetStream();

        while (stream.DataAvailable)
        {
            var numberOfBytesRead = stream.Read(readBuffer, 0, readBuffer.Length);
            if (numberOfBytesRead <= 0)
                break;

            inStream.Write(readBuffer, 0, numberOfBytesRead);
        }

        fullServerReply = Encoding.UTF8.GetString(inStream.ToArray());
    }

    return fullServerReply;
}

private Task WriteStringAsync(TcpClient client, string str)
{
    return Task.Run(() =>
    {
        using (var writer = new StreamWriter(client.GetStream(), new UTF8Encoding(false)))
        {
            writer.Write("HTTP/1.0 200 OK");
            writer.Write(Environment.NewLine);
            writer.Write("Content-Type: text/html; charset=UTF-8");
            writer.Write(Environment.NewLine);
            writer.Write("Content-Length: " + str.Length);
            writer.Write(Environment.NewLine);
            writer.Write(Environment.NewLine);
            writer.Write(str);
        }
    });
}

يمكنك بدء تطبيقك كمسؤول إذا قمت بإضافة بيان تطبيق إلى مشروعك.

فقط أضف عنصرًا جديدًا إلى مشروعك وحدد "ملف بيان التطبيق". غير ال <requestedExecutionLevel> العنصر إلى:

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

بشكل افتراضي ، يحدد Windows البادئة التالية المتاحة للجميع:http: //+: 80/reporary_listen_addresses/

حتى تتمكن من تسجيل الخاص بك HttpListener عبر:

Prefixes.Add("http://+:80/Temporary_Listen_Addresses/" + Guid.NewGuid().ToString("D") + "/";

يؤدي هذا في بعض الأحيان إلى مشاكل في البرامج مثل Skype والتي ستحاول استخدام المنفذ 80 افتراضيًا.

httpListener.Prefixes.Add("http://*:4444/");

يمكنك استخدام "*" حتى تقوم بتنفيذ CMD كمسؤول

netsh http add urlacl url=http://*:4444/ user=username

لا استخدام +، يجب استخدام *، لأنك المواصفات *: 4444 ~.

https://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx

لقد واجهت أيضًا مشكلة مماثلة. إذا كنت قد قمت بالفعل بحجز عنوان URL ، فعليك أولاً حذف عنوان URL للتشغيل في وضع غير المسؤول ، فسيشعر بإنجاز الوصول إلى خطأ.

netsh http delete urlacl url=http://+:80

Netsh يتطلب حقوق المسؤول

يمكنك إصلاح ذلك من أجل المضيف المحلي دون حقوق المسؤول عن طريق تحديد تجاهل expections:

listener.IgnoreWriteExceptions = True
listener.Start()
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top