Question

J'ai une application c # qui s'exécute en tant que service Windows contrôlant les connexions par socket et autres. En outre, il existe une autre application Windows Forms pour contrôler et configurer ce service (systray avec start, stop, show form avec les paramètres de configuration).

J'utilise .net remoting pour effectuer l'IPC et c'était très bien, mais je souhaite maintenant afficher un trafic réel et d'autres rapports, et l'accès à distance ne répondra pas à mes exigences de performances. Je veux donc combiner les deux applications en une.

Voici le problème:

Lorsque j'ai lancé le formulaire à partir du service Windows, rien ne s'est passé. J'ai découvert que je devais cliquer sur le service avec le bouton droit de la souris, accéder à Ouvrir une session, puis cocher la case "Autoriser le service à interagir avec le bureau". option. Puisque je ne veux pas demander à mes utilisateurs de le faire, j'ai à nouveau eu du code googler pour définir cette option dans le regedit de l'utilisateur pendant l'installation. Le problème est que même en paramétrant cette option, cela ne fonctionne pas. Je dois ouvrir les options de connexion du service (c'est coché), décocher et cocher à nouveau.

Alors, comment résoudre ce problème? Quelle est la meilleure façon d’avoir un service Windows avec un contrôle Systray dans le même processus, disponible pour tout utilisateur qui se connecte?

UPDATE: Merci pour les commentaires jusqu'à présent, les gars. Je conviens qu'il est préférable d'utiliser IPC et je sais qu'il est mauvais de combiner des services Windows et des interfaces utilisateur. Même si, je veux savoir comment faire cela.

Était-ce utile?

La solution

Deux processus distincts qui communiquent en utilisant la technologie de votre choix. Les services avec interface utilisateur sont une mauvaise idée . N'allez pas dans cette voie, vous le regretterez.

J'ai eu de très bons résultats avec la communication de service via une simple connexion socket: documentez bien votre protocole de service, gardez-le aussi simple que possible, et ce sera plus facile que vous ne le pensez.

Autres conseils

En pratique, vous ne devez pas associer votre service à l'interface utilisateur de gestion.

Je suis d'accord avec Greg. Peut-être pourriez-vous examiner un mécanisme IPC différent. Peut-être utiliser des sockets et votre propre protocole. Ou, si votre application de contrôle de service ne peut contrôler le service que sur la machine locale, vous pouvez utiliser des canaux nommés (encore plus rapidement).

Voici un moyen de mélanger Services et formulaires

http://www.codeproject.com/KB/system/SystemTrayIconInSvc.aspx

J'ai découvert comment procéder, à partir de this article (cliquez sur le lien "Modifier" du tableau "Méthodes".

string wmiPath = "Win32_Service.Name='" + SERVICE_NAME + "'";
using (ManagementObject service = new ManagementObject(wmiPath))
{
    object[] parameters = new object[11];
    parameters[5] = true;  // Enable desktop interaction
    service.InvokeMethod("Change", parameters);
}

J'ai la solution en quelques étapes, c'est le plan

  1. nous n'allons pas créer de projet de service avec un formulaire Windows, mais plutôt une solution Visual Studio contenant un projet de service Windows, un projet de formulaire Windows et un projet d'installation.

  2. L'idée est de disposer d'une base de données, d'un fichier ou de tout ce que vous êtes en mesure de stocker des données dans lesquelles vous stockeriez les paramètres que votre service Windows utilisera toujours pour s'exécuter. Ainsi, votre service Windows et votre application de formulaire Windows devraient pouvoir modifier et extraire des données de celui-ci.

  3. Dans le formulaire principal de votre application Windows, faites glisser un NotifyIcon sur le formulaire, dans l'onglet Propriétés, parcourez et sélectionnez une image .ico (vous pouvez en créer une dans visual studio, mais vous pouvez également Allez sur google ou contactez-moi). Cela s'affichera dans la barre d'état système lorsque vous exécuterez l'application et que le formulaire principal est actif ou affiché, essayez-le, exécutez l'application.

  4. Ajoutez les deux en tant que sorties dans le projet d'installation de la solution. Pour ajouter un projet à un projet d'installation, ils doivent appartenir à la même solution. Cliquez avec le bouton droit de la souris sur le projet d'installation dans l'explorateur de solutions, mettez en surbrillance ajouter, puis sélectionnez la sortie du projet, ajoutez le service Windows et les sorties de formulaire Windows et vous les verrez dans l'explorateur de solutions sous le projet d'installation.

  5. l'ajout d'un service Windows va plus loin que cela, mais c'est aussi un autre sujet google it

  6. Créer un raccourci pour l'application Windows et l'ajouter au dossier de démarrage constitue également un autre sujet, google ou contactez-moi.

    REMARQUE: Programmez votre formulaire de manière à ce que le bouton de fermeture ne s'affiche pas et que le formulaire devienne Me.visible = false et double-cliquer sur l'icône dans la barre d'état système est le seul moyen de définir me.visible = true.that Chaque fois que l’ordinateur démarre, votre application Windows Form est également lancée et visible est immédiatement définie sur false, mais comme elle comporte un notifyicon avec une icône, elle s’affichera dans la barre des tâches système et un double-clic rendra le formulaire visible pour modifier le paramètres que vous stockez pour le service, le service démarre également automatiquement puisque vous l’auriez configuré lors de la configuration du service dans le projet de configuration. mon courrier est iamjavademon@gmail.com pour une meilleure illustration en utilisant des captures d’écran et explique en détail

C’est très simple: vous devez créer un seul thread pour effectuer des événements d’application. Comme ceci (code source pour C ++ avec CLR, mais vous pouvez le faire en C #):

ref class RunWindow{
public:
    static void MakeWindow(Object^ data)
    {
        Application::EnableVisualStyles();
        Application::SetCompatibleTextRenderingDefault(false); 

        Application::Run(gcnew TMainForm());
    };
};

Et créez un fil dans main

int main(array<System::String ^> ^args)
{
    bool bService = RunAsService(L"SimpleServiceWithIconInTrayAndWindow");

    if (bService)
    {

        System::Threading::Thread ^thread = gcnew System::Threading::Thread(gcnew ParameterizedThreadStart(RunWindow::MakeWindow));
        thread->Start();

        ServiceBase::Run(gcnew simpleWinService());
        Application::Exit();
    }
    else
    {
        Application::EnableVisualStyles();
        Application::SetCompatibleTextRenderingDefault(false); 

        // Create the main window and run it
        Application::Run(gcnew TMainForm());
    }

    return 0;
}

Les principaux problèmes des services interactifs sont les suivants:

  • Sécurité - un autre processus pourrait lui envoyer des messages via sa pompe de messages, permettant ainsi d'accéder à un processus SYSTEM / LOCAL.

  • Inachevé - un service interactif ne voit jamais les messages du shell et ne peut donc pas interagir avec les icônes de la zone de notification.

Nous utilisons régulièrement les connexions TCP et UDP pour transmettre les informations des services à d'autres exes et, dans certains cas, à MSMQ.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top