Forráskód Böngészése

Bug 2079: Allow opening all sites in a folder in PuTTY (2nd) + Cleaning up temporary WinSCP PuTTY sessions

https://winscp.net/tracker/2079

Source commit: d0f024226ec3c6fd5b134f8a06c35dfb912d68f4
Martin Prikryl 3 éve
szülő
commit
7b8d29ed76
3 módosított fájl, 123 hozzáadás és 6 törlés
  1. 1 1
      source/forms/SiteAdvanced.cpp
  2. 121 4
      source/windows/GUITools.cpp
  3. 1 1
      source/windows/GUITools.h

+ 1 - 1
source/forms/SiteAdvanced.cpp

@@ -426,7 +426,7 @@ void __fastcall TSiteAdvancedDialog::LoadSession()
     FColor = (TColor)FSessionData->Color;
   }
 
-  EnableControl(PuttyGroup, !DoesSessionExistInPutty(FSessionData));
+  EnableControl(PuttyGroup, !DoesSessionExistInPutty(FSessionData->StorageKey));
 
   UpdateControls();
 }

+ 121 - 4
source/windows/GUITools.cpp

@@ -29,6 +29,7 @@
 #include <vssym32.h>
 #include <DateUtils.hpp>
 #include <IOUtils.hpp>
+#include <Queue.h>
 
 #include "Animations96.h"
 #include "Animations120.h"
@@ -94,11 +95,11 @@ bool __fastcall FindFile(UnicodeString & Path)
   return Result;
 }
 //---------------------------------------------------------------------------
-bool DoesSessionExistInPutty(TSessionData * SessionData)
+bool DoesSessionExistInPutty(const UnicodeString & StorageKey)
 {
   std::unique_ptr<TRegistryStorage> Storage(new TRegistryStorage(Configuration->PuttySessionsKey));
   Storage->ConfigureForPutty();
-  return Storage->OpenRootKey(true) && Storage->KeyExists(SessionData->StorageKey);
+  return Storage->OpenRootKey(true) && Storage->KeyExists(StorageKey);
 }
 //---------------------------------------------------------------------------
 bool __fastcall ExportSessionToPutty(TSessionData * SessionData, bool ReuseExisting, const UnicodeString & SessionName)
@@ -148,6 +149,112 @@ bool __fastcall ExportSessionToPutty(TSessionData * SessionData, bool ReuseExist
   return Result;
 }
 //---------------------------------------------------------------------------
+class TPuttyCleanupThread : public TSimpleThread
+{
+public:
+  static void Schedule();
+
+protected:
+  virtual void __fastcall Execute();
+  virtual void __fastcall Terminate();
+  bool __fastcall Finished();
+  void DoSchedule();
+
+private:
+  TDateTime FTimer;
+  static TPuttyCleanupThread * FInstance;
+  static std::unique_ptr<TCriticalSection> FSection;
+};
+//---------------------------------------------------------------------------
+TPuttyCleanupThread * TPuttyCleanupThread::FInstance(NULL);
+std::unique_ptr<TCriticalSection> TPuttyCleanupThread::FSection(TraceInitPtr(new TCriticalSection()));
+//---------------------------------------------------------------------------
+void TPuttyCleanupThread::Schedule()
+{
+  TGuard Guard(FSection.get());
+  if (FInstance == NULL)
+  {
+    FInstance = new TPuttyCleanupThread();
+    FInstance->DoSchedule();
+    FInstance->Start();
+  }
+  else
+  {
+    FInstance->DoSchedule();
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPuttyCleanupThread::Execute()
+{
+  std::unique_ptr<TStrings> Sessions(new TStringList());
+
+  do
+  {
+    {
+      TGuard Guard(FSection.get());
+      std::unique_ptr<TRegistryStorage> Storage(new TRegistryStorage(Configuration->PuttySessionsKey));
+      Storage->AccessMode = smReadWrite;
+      Storage->ConfigureForPutty();
+
+      std::unique_ptr<TStringList> Sessions2(new TStringList());
+      if (Storage->OpenRootKey(true))
+      {
+        std::unique_ptr<TStrings> SubKeys(new TStringList());
+        Storage->GetSubKeyNames(SubKeys.get());
+        for (int Index = 0; Index < SubKeys->Count; Index++)
+        {
+          UnicodeString SessionName = SubKeys->Strings[Index];
+          if (StartsStr(GUIConfiguration->PuttySession, SessionName))
+          {
+            Sessions2->Add(SessionName);
+          }
+        }
+
+        Sessions2->Sort();
+        if (!Sessions->Equals(Sessions2.get()))
+        {
+          // Just in case new sessions from another WinSCP instance are added, delay the cleanup
+          // (to avoid having to implement some inter-process communication).
+          // Both instances will attempt to do the cleanup, but that not a problem
+          Sessions->Assign(Sessions2.get());
+          DoSchedule();
+        }
+      }
+
+      if (FTimer < Now())
+      {
+        for (int Index = 0; Index < Sessions->Count; Index++)
+        {
+          UnicodeString SessionName = Sessions->Strings[Index];
+          Storage->RecursiveDeleteSubKey(SessionName);
+        }
+
+        FInstance = NULL;
+        return;
+      }
+    }
+
+    Sleep(1000);
+  }
+  while (true);
+}
+//---------------------------------------------------------------------------
+void __fastcall TPuttyCleanupThread::Terminate()
+{
+  DebugFail();
+}
+//---------------------------------------------------------------------------
+bool __fastcall TPuttyCleanupThread::Finished()
+{
+  // self-destroy
+  return TSimpleThread::Finished() || true;
+}
+//---------------------------------------------------------------------------
+void TPuttyCleanupThread::DoSchedule()
+{
+  FTimer = IncSecond(Now(), 10);
+}
+//---------------------------------------------------------------------------
 void OpenSessionInPutty(TSessionData * SessionData)
 {
   // putty does not support resolving environment variables in session settings
@@ -249,13 +356,23 @@ void OpenSessionInPutty(TSessionData * SessionData)
       else
       {
         UnicodeString SessionName;
-        if (ExportSessionToPutty(SessionData, true, GUIConfiguration->PuttySession))
+
+        UnicodeString PuttySession = GUIConfiguration->PuttySession;
+        int Uniq = 1;
+        while (DoesSessionExistInPutty(PuttySession))
+        {
+          Uniq++;
+          PuttySession = FORMAT(L"%s (%d)", (GUIConfiguration->PuttySession, Uniq));
+        }
+
+        if (ExportSessionToPutty(SessionData, true, PuttySession))
         {
           SessionName = SessionData->SessionName;
         }
         else
         {
-          SessionName = GUIConfiguration->PuttySession;
+          SessionName = PuttySession;
+          TPuttyCleanupThread::Schedule();
           if ((SessionData->FSProtocol == fsFTP) &&
               GUIConfiguration->TelnetForFtpInPutty)
           {

+ 1 - 1
source/windows/GUITools.h

@@ -22,7 +22,7 @@ void __fastcall ExecuteShellCheckedAndWait(const UnicodeString Command, TProcess
 TObjectList * StartCreationDirectoryMonitorsOnEachDrive(unsigned int Filter, TFileChangedEvent OnChanged);
 extern bool DontCopyCommandToClipboard;
 bool __fastcall CopyCommandToClipboard(const UnicodeString & Command);
-bool DoesSessionExistInPutty(TSessionData * SessionData);
+bool DoesSessionExistInPutty(const UnicodeString & StorageKey);
 bool __fastcall ExportSessionToPutty(TSessionData * SessionData, bool ReuseExisting, const UnicodeString & SessionName);
 void OpenSessionInPutty(TSessionData * SessionData);
 bool __fastcall SpecialFolderLocation(int PathID, UnicodeString & Path);