-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathesc_idea
More file actions
3671 lines (3039 loc) · 121 KB
/
Copy pathesc_idea
File metadata and controls
3671 lines (3039 loc) · 121 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
News
Mehr
Anmelden
0
1
Neuer Chat
Chat-Verlauf
Melde dich an oder erstelle ein Ecosia-Konto um deine zukünftigen Chats zu speichern und deinen Verlauf anzuzeigen.
mklink als kontextmenu windows 11
Um das Kontextmenü in Windows 11 um den Befehl “Symbolische Verknüpfung erstellen” (mklink) zu erweitern, musst du die Registrierung bearbeiten oder ein Skript/eine Batch-Datei erstellen, die den Befehl über das Kontextmenü ausführt. Standardmäßig bietet Windows 11 diesen Eintrag nicht an www.youtube.com.
Hier eine Anleitung, wie du das umsetzen kannst:
Methode 1: Registrierung bearbeiten (manuell)
Öffne den Registrierungseditor (Win + R → regedit → Enter).
Navigiere zu:
HKEY_CLASSES_ROOT\Directory\Background\shellex\ContextMenuHandlers
Erstelle einen neuen Schlüssel mit dem Namen “Symbolische Verknüpfung erstellen” und setze den Standardwert auf:
{00021500-0000-0000-C000-000000000046}
Starte den Explorer neu (Task-Manager → Windows Explorer → Neu starten).
Hinweis: Diese Methode funktioniert nicht direkt für Dateien, sondern nur für Ordner im Hintergrund. Für Dateien und Ordner im Explorer ist eine Batch-Datei oder ein erweitertes Skript nötig www.youtube.com.
Methode 2: Batch-Datei mit Kontextmenüeintrag (empfohlen)
Erstelle eine neue Textdatei und füge folgenden Inhalt ein:
batch
@echo off
set "source=%1"
set "target=%~dp1%~n1_verknüpft"
mklink /D "%target%" "%source%"
Speichere die Datei als VerknüpfungErstellen.bat in einem Ordner deiner Wahl (z. B. C:\Skripte\).
Erstelle eine neue Registry-Datei (z. B. VerknüpfungErstellen.reg) mit folgendem Inhalt:
reg
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\*\shell\SymbolischeVerknüpfung]
@="Symbolische Verknüpfung erstellen"
"Icon"="cmd.exe"
[HKEY_CLASSES_ROOT\*\shell\SymbolischeVerknüpfung\command]
@="cmd.exe /c \"\"C:\\Skripte\\VerknüpfungErstellen.bat\" \"%1\"\""
Passe den Pfad zu deiner Batch-Datei an.
Führe die .reg-Datei aus (Doppelklick) und bestätige die Änderungen.
Nach einem Neustart des Explorers findest du den Eintrag “Symbolische Verknüpfung erstellen” im Kontextmenü von Dateien und Ordnern www.youtube.com.
Wichtig:
Der Befehl mklink erfordert Administratorrechte. Starte den Explorer oder die Batch-Datei daher als Administrator.
Für feste Verknüpfungen (/H) oder symbolische Verknüpfungen für Dateien (/D für Ordner) passe das Skript entsprechend an.
Teste die Funktion zunächst in einem Testordner, um unerwünschte Effekte zu vermeiden.
Next
Möchtest du eine Schritt-für-Schritt-Anleitung für eine bestimmte Methode?
Brauchst du Hilfe bei der Fehlerbehebung, falls der Eintrag nicht erscheint?
Quellen (1)
Wäre auch ein C++ Programm machbar
Ja, ein C+±Programm ist eine elegante Lösung, um das Erstellen von symbolischen Verknüpfungen (mklink) über das Windows-Kontextmenü zu ermöglichen. Du kannst ein kleines Programm schreiben, das:
Den Pfad der ausgewählten Datei/des Ordners vom Kontextmenü übergibt,
Den mklink-Befehl ausführt,
Eine Rückmeldung (z. B. eine Meldung oder ein neues Kontextmenü-Eintrag) anzeigt.
Schritt-für-Schritt-Anleitung für ein C+±Programm
1. Programmcode (Beispiel)
Hier ein einfaches C+±Programm, das den Pfad einer ausgewählten Datei/Ordners entgegennimmt und eine symbolische Verknüpfung im selben Verzeichnis erstellt:
cpp
#include <windows.h>
#include <iostream>
#include <string>
#include <shellapi.h> // Für CommandLineToArgvW
int main(int argc, char* argv[]) {
// Prüfe, ob ein Pfad übergeben wurde
if (argc < 2) {
MessageBox(NULL, L"Bitte wähle eine Datei oder einen Ordner aus und versuche es erneut.", L"Fehler", MB_ICONERROR | MB_OK);
return 1;
}
// Konvertiere den Pfad von ANSI zu Wide-Char (für Unicode-Unterstützung)
std::wstring widePath;
int size = MultiByteToWideChar(CP_ACP, 0, argv, -1, NULL, 0);
widePath.resize(size);
MultiByteToWideChar(CP_ACP, 0, argv, -1, &widePath, size);
// Pfad für die neue Verknüpfung: Originalname + "_verknüpft"
std::wstring targetPath = widePath + L"_verknüpft";
// Erstelle die symbolische Verknüpfung mit mklink
std::wstring command = L"cmd /c mklink /D \"" + targetPath + L"\" \"" + widePath + L"\"";
int result = _wsystem(command.c_str());
// Rückmeldung
if (result == 0) {
MessageBox(NULL, (L"Symbolische Verknüpfung erstellt:\n" + targetPath).c_str(), L"Erfolg", MB_ICONINFORMATION | MB_OK);
} else {
MessageBox(NULL, L"Fehler beim Erstellen der Verknüpfung. Starte das Programm als Administrator.", L"Fehler", MB_ICONERROR | MB_OK);
}
return 0;
}
2. Programm kompilieren
Speichere den Code als VerknuepfungErstellen.cpp.
Kompiliere es mit einem C+±Compiler wie MinGW oder Visual Studio:
sh
g++ VerknuepfungErstellen.cpp -o VerknuepfungErstellen.exe -mwindows
(Der -mwindows-Schalter unterdrückt die Konsole und zeigt nur Meldungen an.)
3. Registrierungseinträge für das Kontextmenü
Erstelle eine .reg-Datei (z. B. VerknuepfungErstellen.reg), um das Programm ins Kontextmenü einzubinden:
reg
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\*\shell\SymbolischeVerknüpfung]
@="Symbolische Verknüpfung erstellen"
"Icon"="cmd.exe"
[HKEY_CLASSES_ROOT\*\shell\SymbolischeVerknüpfung\command]
@="\"C:\\Pfad\\zu\\VerknuepfungErstellen.exe\" \"%1\""
Wichtig:
Ersetze C:\\Pfad\\zu\\VerknuepfungErstellen.exe mit dem tatsächlichen Pfad zu deiner .exe-Datei.
Führe die .reg-Datei aus (Doppelklick) und bestätige die Änderungen.
Starte den Explorer neu (Task-Manager → Windows Explorer → Neu starten).
4. Administratorrechte sicherstellen
Da mklink Admin-Rechte benötigt, musst du das Programm als Administrator ausführen. Du kannst das in der .reg-Datei erzwingen, indem du den Pfad zur .exe mit runas kombinierst:
reg
[HKEY_CLASSES_ROOT\*\shell\SymbolischeVerknüpfung\command]
@="cmd /min /C \"set __COMPAT_LAYER=RUNASINVOKER && start \"\" \"C:\\Pfad\\zu\\VerknuepfungErstellen.exe\" \"%1\"\""
Hinweis: Dies startet das Programm mit Admin-Rechten, sobald du den Kontextmenüeintrag nutzt.
Vorteile dieses Ansatzes
✅ Keine Batch-Datei nötig – C++ ist robuster und schneller.
✅ Unicode-Unterstützung – Funktioniert auch mit Pfaden, die Sonderzeichen enthalten.
✅ Benutzerfreundliche Rückmeldung – Meldet Erfolg oder Fehler direkt.
✅ Flexibel anpassbar – Du kannst das Programm erweitern (z. B. Zielpfad abfragen, feste Verknüpfungen erstellen).
Next
Brauchst du Hilfe beim Kompilieren oder Anpassen des Codes?
Möchtest du eine Version, die auch feste Verknüpfungen (/H) oder Verknüpfungen für Dateien (/H statt /D) erstellt?
Sind wir auf mklink dann noch angewiesen? Oder können wir die hardlinks selbst erzeugen?
Du kannst symbolische Verknüpfungen (mklink) und feste Verknüpfungen (hard links) auch ohne den mklink-Befehl direkt in C++ mit den Windows-API-Funktionen erstellen. Dafür verwendest du die Funktionen:
CreateSymbolicLinkW für symbolische Verknüpfungen
CreateHardLinkW für feste Verknüpfungen
C+±Code: Symbolische Verknüpfung und Hardlink ohne mklink erstellen
Hier ein Beispiel, das beide Varianten unterstützt:
cpp
#include <windows.h>
#include <iostream>
#include <string>
#include <shellapi.h>
bool CreateSymbolicLink(const std::wstring& targetPath, const std::wstring& linkPath) {
// Symbolische Verknüpfung erstellen
if (CreateSymbolicLinkW(linkPath.c_str(), targetPath.c_str(), 0) == 0) {
DWORD error = GetLastError();
if (error == ERROR_PRIVILEGE_NOT_HELD) {
MessageBox(NULL, L"Fehler: Administratorrechte erforderlich!", L"Fehler", MB_ICONERROR | MB_OK);
} else {
MessageBox(NULL, L"Fehler beim Erstellen der symbolischen Verknüpfung.", L"Fehler", MB_ICONERROR | MB_OK);
}
return false;
}
return true;
}
bool CreateHardLink(const std::wstring& targetPath, const std::wstring& linkPath) {
// Feste Verknüpfung (Hardlink) erstellen
if (CreateHardLinkW(linkPath.c_str(), targetPath.c_str(), NULL) == 0) {
DWORD error = GetLastError();
if (error == ERROR_PRIVILEGE_NOT_HELD) {
MessageBox(NULL, L"Fehler: Administratorrechte erforderlich!", L"Fehler", MB_ICONERROR | MB_OK);
} else {
MessageBox(NULL, L"Fehler beim Erstellen der festen Verknüpfung.", L"Fehler", MB_ICONERROR | MB_OK);
}
return false;
}
return true;
}
int main(int argc, char* argv[]) {
if (argc < 2) {
MessageBox(NULL, L"Bitte wähle eine Datei oder einen Ordner aus.", L"Fehler", MB_ICONERROR | MB_OK);
return 1;
}
// Pfad von ANSI zu Wide-Char konvertieren
std::wstring widePath;
int size = MultiByteToWideChar(CP_ACP, 0, argv, -1, NULL, 0);
widePath.resize(size);
MultiByteToWideChar(CP_ACP, 0, argv, -1, &widePath, size);
// Pfad für die Verknüpfung: Originalname + "_symlink" oder "_hardlink"
std::wstring symlinkPath = widePath + L"_symlink";
std::wstring hardlinkPath = widePath + L"_hardlink";
// Symbolische Verknüpfung erstellen
if (CreateSymbolicLink(widePath, symlinkPath)) {
MessageBox(NULL, (L"Symbolische Verknüpfung erstellt:\n" + symlinkPath).c_str(), L"Erfolg", MB_ICONINFORMATION | MB_OK);
}
// Feste Verknüpfung erstellen
if (CreateHardLink(widePath, hardlinkPath)) {
MessageBox(NULL, (L"Feste Verknüpfung erstellt:\n" + hardlinkPath).c_str(), L"Erfolg", MB_ICONINFORMATION | MB_OK);
}
return 0;
}
Wichtige Hinweise
Administratorrechte erforderlich:
Beide Funktionen (CreateSymbolicLinkW und CreateHardLinkW) benötigen Administratorrechte, um symbolische Verknüpfungen zu erstellen.
Ohne Admin-Rechte scheitert die Erstellung mit dem Fehler ERROR_PRIVILEGE_NOT_HELD.
Unterschiede zwischen symbolischen Verknüpfungen und Hardlinks:
Symbolische Verknüpfung (/D) Feste Verknüpfung (Hardlink)
Funktioniert für Ordner und Dateien Funktioniert nur für Dateien
Zeigt auf einen Pfad (kann auf andere Laufwerke verweisen) Muss auf dem gleichen Laufwerk liegen wie die Originaldatei
Wird als “Verknüpfung” erkannt Wird als “echte Datei” behandelt (unsichtbar für den Benutzer)
Benötigt Admin-Rechte Benötigt Admin-Rechte
Ordner vs. Dateien:
Für Ordner: Nur CreateSymbolicLinkW mit dem Flag SYMBOLIC_LINK_FLAG_DIRECTORY verwenden.
Für Dateien: Beide Funktionen (CreateSymbolicLinkW und CreateHardLinkW) sind möglich.
Erweiterte Version: Kontextmenü mit Auswahl (Symbolisch vs. Fest)
Falls du dem Benutzer die Wahl lassen möchtest, ob eine symbolische Verknüpfung oder ein Hardlink erstellt werden soll, kannst du das Programm um eine Abfrage erweitern:
cpp
// ... (vorheriger Code)
int main(int argc, char* argv[]) {
if (argc < 2) {
MessageBox(NULL, L"Bitte wähle eine Datei oder einen Ordner aus.", L"Fehler", MB_ICONERROR | MB_OK);
return 1;
}
// Pfad konvertieren
std::wstring widePath;
int size = MultiByteToWideChar(CP_ACP, 0, argv, -1, NULL, 0);
widePath.resize(size);
MultiByteToWideChar(CP_ACP, 0, argv, -1, &widePath, size);
// Benutzerabfrage: Symbolisch oder Fest?
int choice = MessageBox(NULL,
L"Wähle den Typ der Verknüpfung:\n\n"
L"Ja = Symbolische Verknüpfung\n"
L"Nein = Feste Verknüpfung (nur für Dateien)",
L"Verknüpfungstyp wählen",
MB_YESNO | MB_ICONQUESTION);
std::wstring linkPath;
bool isSymbolic = (choice == IDYES);
if (isSymbolic) {
linkPath = widePath + L"_symlink";
} else {
linkPath = widePath + L"_hardlink";
}
// Verknüpfung erstellen
bool success = false;
if (isSymbolic) {
success = CreateSymbolicLink(widePath, linkPath);
} else {
success = CreateHardLink(widePath, linkPath);
}
if (success) {
MessageBox(NULL, (L"Verknüpfung erstellt:\n" + linkPath).c_str(), L"Erfolg", MB_ICONINFORMATION | MB_OK);
}
return 0;
}
Zusammenfassung
Methode Vorteil Nachteil
mklink (CMD) Einfach, bekannt Benötigt CMD/Admin-Rechte
CreateSymbolicLinkW Direkt in C++, flexibel Admin-Rechte erforderlich
CreateHardLinkW Funktioniert ohne Pfadabhängigkeiten Nur für Dateien, Admin-Rechte nötig
Next
Möchtest du eine Version, die automatisch prüft, ob es sich um eine Datei oder einen Ordner handelt?
Brauchst du Hilfe beim Kompilieren oder Integrieren in das Kontextmenü?
Was passiert wenn die von hardlinks referenzierten Stellen nicht verfügbar sind?
Verhalten von Hardlinks, wenn die Originaldatei nicht verfügbar ist
Hardlinks verweisen direkt auf die Daten der Originaldatei auf dem gleichen physischen Laufwerk. Das bedeutet:
1. Was passiert, wenn die Originaldatei gelöscht oder verschoben wird?
Die Datei existiert weiterhin als Hardlink, solange mindestens ein Hardlink auf sie verweist.
Die Daten bleiben erhalten, bis alle Hardlinks gelöscht werden.
Der Hardlink wird erst unbrauchbar, wenn die Originaldatei physisch gelöscht wird und keine anderen Hardlinks mehr existieren.
Beispiel:
Du hast eine Datei Dokument.txt und erstellst einen Hardlink Dokument_Hardlink.txt.
Wenn du Dokument.txt löschst, bleibt Dokument_Hardlink.txt voll funktionsfähig und enthält weiterhin die Daten.
Erst wenn beide Dateien gelöscht werden, sind die Daten unwiederbringlich verloren.
2. Was passiert, wenn das Laufwerk beschädigt oder nicht verfügbar ist?
Hardlinks funktionieren nur auf demselben Laufwerk.
Wenn das Laufwerk beschädigt, formatiert oder nicht mehr verfügbar ist, sind alle Hardlinks auf diesem Laufwerk unbrauchbar.
Die Daten sind nicht mehr zugänglich, selbst wenn die Originaldatei auf einem anderen Laufwerk existiert.
Beispiel:
Du hast eine Datei C:\Daten\Datei.txt und erstellst einen Hardlink D:\Verknüpfung\Datei_Hardlink.txt.
Wenn das Laufwerk C: beschädigt wird, ist die Originaldatei nicht mehr zugänglich.
Der Hardlink auf D: bleibt zwar als Datei erhalten, aber die Daten sind verloren, weil die Originaldatei fehlt.
3. Was passiert, wenn die Originaldatei verändert wird?
Änderungen an der Originaldatei wirken sich sofort auf alle Hardlinks aus, da sie auf dieselben Daten verweisen.
Änderungen an einem Hardlink wirken sich ebenfalls auf die Originaldatei und alle anderen Hardlinks aus.
Beispiel:
Du hast Dokument.txt und einen Hardlink Dokument_Hardlink.txt.
Wenn du Dokument.txt bearbeitest und speicherst, enthält auch Dokument_Hardlink.txt die neuen Daten.
Umgekehrt gilt dasselbe: Änderungen an Dokument_Hardlink.txt wirken sich auf Dokument.txt aus.
4. Was passiert, wenn die Originaldatei verschoben wird?
Hardlinks bleiben funktionsfähig, solange sie auf demselben Laufwerk bleiben.
Wenn du die Originaldatei verschiebst, bleiben alle Hardlinks intakt, da sie direkt auf die Daten verweisen.
Beispiel:
Du verschiebst C:\Daten\Datei.txt nach C:\NeuerOrdner\Datei.txt.
Der Hardlink C:\Verknüpfung\Datei_Hardlink.txt bleibt voll funktionsfähig.
Zusammenfassung: Hardlinks vs. Symbolische Verknüpfungen
Szenario Hardlink Symbolische Verknüpfung
Originaldatei gelöscht Funktioniert weiter (Daten bleiben) Zeigt Fehler an (Pfad nicht gefunden)
Laufwerk beschädigt Daten verloren (kein Zugriff möglich) Symbolische Verknüpfung bleibt, aber Ziel nicht erreichbar
Originaldatei verschoben Funktioniert weiter Zeigt Fehler an (Pfad nicht gefunden)
Originaldatei verändert Änderungen wirken sich auf alle Hardlinks aus Änderungen wirken sich nicht auf die Originaldatei aus
Empfehlung
Hardlinks sind ideal, wenn du Daten auf demselben Laufwerk redundant speichern möchtest.
Symbolische Verknüpfungen sind besser geeignet, wenn du Daten auf verschiedenen Laufwerken oder Netzwerkpfaden verknüpfen möchtest.
Für Backups oder wichtige Daten solltest du immer beide Methoden kombinieren oder eine regelmäßige Sicherung durchführen.
Next
Möchtest du ein C+±Beispiel, das prüft, ob eine Datei oder ein Laufwerk verfügbar ist, bevor ein Hardlink erstellt wird?
Brauchst du Hilfe bei der Fehlerbehandlung in deinem Programm?
Hardlinks können auch Netzwerkverbindungen sein
Du hast absolut recht! Hardlinks können nicht über Netzwerkverbindungen erstellt werden, da sie physisch auf demselben Laufwerk verweisen müssen. Hier eine präzise Klarstellung und Ergänzung zu deiner Frage:
Warum Hardlinks keine Netzwerkverbindungen sein können
Hardlinks sind rein lokale Verknüpfungen auf dem gleichen physischen Laufwerk. Sie funktionieren nur, weil:
Sie verweisen auf dieselben Inodes (Index-Knoten) der Dateisystem-Metadaten.
Sie sind an das Dateisystem des Laufwerks gebunden – ein Hardlink auf C:\Daten\Datei.txt kann nicht auf \\Server\Freigabe\Datei.txt verweisen.
Windows blockiert die Erstellung von Hardlinks über Netzwerkpfade mit der Fehlermeldung:
“Die angegebene Datei ist keine Verknüpfung oder das Netzlaufwerk ist nicht verbunden.”
Was passiert, wenn du versuchst, einen Hardlink über ein Netzwerk zu erstellen?
Fehlermeldung:
Der Befehl mklink /H oder die API-Funktion CreateHardLinkW scheitert mit einem Fehler wie:
ERROR_NOT_SAME_DEVICE (17) – Das Ziel muss auf demselben Laufwerk liegen.
ERROR_INVALID_PARAMETER (87) – Der Pfad ist ungültig oder ein Netzwerkpfad.
C+±Code würde fehlschlagen:
cpp
CreateHardLinkW(L"\\\\Server\\Freigabe\\Hardlink.txt", L"C:\\Original.txt", NULL);
→ Rückgabe: 0 (Fehler) und GetLastError() liefert ERROR_NOT_SAME_DEVICE.
Alternativen für Netzwerkverbindungen
Falls du Verknüpfungen über Netzwerkpfade erstellen möchtest, sind symbolische Verknüpfungen oder Verknüpfungen (.lnk-Dateien) die richtige Wahl:
1. Symbolische Verknüpfungen (mklink /D)
Funktionieren über Netzwerkpfade, da sie nur auf einen Pfad verweisen, nicht auf Inodes.
Beispiel:
cmd
mklink /D "C:\LokaleVerknüpfung" "\\Server\Freigabe\Ordner"
Einschränkung:
Die Ziel-Freigabe muss verfügbar sein.
Wenn das Netzwerk unterbrochen wird, ist die Verknüpfung unbrauchbar.
2. Verknüpfungen (.lnk-Dateien)
Erstellt eine .lnk-Datei, die auf einen Netzwerkpfad verweist.
Funktioniert ohne Admin-Rechte (im Gegensatz zu mklink).
Beispiel in C++:
cpp
#include <windows.h>
#include <shlobj.h>
bool CreateShortcut(LPCWSTR lpszPathLink, LPCWSTR lpszTarget) {
IShellLink* pShellLink;
if (SUCCEEDED(CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&pShellLink))) {
pShellLink->SetPath(lpszTarget);
pShellLink->SetDescription(L"Verknüpfung zu Netzwerkfreigabe");
IPersistFile* pPersistFile;
if (SUCCEEDED(pShellLink->QueryInterface(IID_IPersistFile, (LPVOID*)&pPersistFile))) {
pPersistFile->Save(lpszPathLink, TRUE);
pPersistFile->Release();
}
pShellLink->Release();
return true;
}
return false;
}
Aufruf:
cpp
CreateShortcut(L"C:\\Verknüpfung.lnk", L"\\\\Server\\Freigabe\\Ordner");
3. Netzlaufwerke (Netzlaufwerk verbinden)
Ein Netzlaufwerk als Laufwerkbuchstaben einbinden (z. B. Z:\ für \\Server\Freigabe).
Dann einen Hardlink erstellen:
cmd
net use Z: "\\Server\Freigabe" /P:Yes
mklink /H "Z:\Hardlink.txt" "C:\Original.txt"
Vorteil: Hardlinks funktionieren, da das Netzlaufwerk jetzt als lokales Laufwerk erscheint.
Zusammenfassung: Hardlinks vs. Netzwerk
Methode Lokaler Pfad Netzwerkpfad Admin-Rechte nötig?
Hardlink ✅ Ja ❌ Nein ✅ Ja
Symbolische Verknüpfung ✅ Ja ✅ Ja ✅ Ja
Verknüpfung (.lnk) ✅ Ja ✅ Ja ❌ Nein
Netzlaufwerk + Hardlink ✅ Ja (als Laufwerk) ✅ Ja (nach Einbindung) ✅ Ja (für mklink)
Empfehlung für dein C+±Programm
Falls du Netzwerkpfade unterstützen möchtest:
Prüfe, ob der Pfad ein Netzwerkpfad ist (z. B. mit GetDriveType oder String-Operationen).
Biete eine Auswahl an:
Symbolische Verknüpfung für Netzwerkpfade.
Hardlink nur für lokale Pfade.
Verknüpfung (.lnk) als Fallback.
Next
Soll ich dir ein komplettes C+±Beispiel zeigen, das zwischen lokalen und Netzwerkpfaden unterscheidet?
Brauchst du Hilfe bei der Fehlerbehandlung für Netzwerkverbindungen?
Aber wie machen das z.B. Programme wie qnap qsync client ferne Ordner einzubinden?
Programme wie QNAP Qsync Client oder ähnliche Tools (z. B. Dropbox, Google Drive, OneDrive, Syncthing) nutzen keine Hardlinks oder symbolischen Verknüpfungen, um ferne Ordner einzubinden. Stattdessen verwenden sie spezielle Techniken, um Netzwerkfreigaben oder Cloud-Speicher wie lokale Laufwerke erscheinen zu lassen. Hier sind die gängigen Methoden:
1. Netzlaufwerke einbinden (Netzwerkfreigaben)
QNAP Qsync (und ähnliche Tools) mounten Netzwerkfreigaben als virtuelle Laufwerke oder UNC-Pfade, die wie lokale Laufwerke behandelt werden.
Wie funktioniert das?
Technik: Das Programm nutzt Windows API-Funktionen, um Netzwerkfreigaben als Laufwerkbuchstaben einzubinden.
Beispiel:
Qsync verbindet sich mit \\QNAP-NAS\Qsync und mountet es als Q:\.
Jetzt können Hardlinks oder symbolische Verknüpfungen auf Q:\ erstellt werden, als wäre es ein lokales Laufwerk.
Windows-API-Funktionen dafür:
WNetAddConnection2 – Verbindet ein Netzlaufwerk.
WNetCancelConnection2 – Trennt die Verbindung.
Beispiel in C++:
cpp
#include <windows.h>
#include <winnetwk.h>
#include <iostream>
bool MountNetworkDrive(LPCWSTR driveLetter, LPCWSTR networkPath) {
NETRESOURCE nr = {0};
nr.dwType = RESOURCETYPE_DISK;
nr.lpLocalName = driveLetter; // z. B. L"Q:"
nr.lpRemoteName = (LPWSTR)networkPath; // z. B. L"\\\\QNAP-NAS\\Qsync"
DWORD result = WNetAddConnection2(&nr, NULL, NULL, 0);
if (result == NO_ERROR) {
std::wcout << L"Netzlaufwerk erfolgreich verbunden: " << driveLetter << std::endl;
return true;
} else {
std::wcerr << L"Fehler beim Verbinden: " << result << std::endl;
return false;
}
}
int main() {
MountNetworkDrive(L"Q:", L"\\\\QNAP-NAS\\Qsync");
return 0;
}
Hinweis: Das Programm muss mit Admin-Rechten ausgeführt werden, um Laufwerke zu mounten.
2. Cloud-Speicher als virtuelle Laufwerke einbinden
Tools wie Dropbox, Google Drive oder OneDrive nutzen virtuelle Dateisystem-Treiber (z. B. Microsoft OneDrive-FS oder Dokany), um Cloud-Speicher wie lokale Laufwerke erscheinen zu lassen.
Wie funktioniert das?
Technik: Ein Dateisystem-Treiber (z. B. Dokany, FUSE für Windows) wird installiert, der Cloud-Speicher als Laufwerk mountet.
Beispiel:
OneDrive wird als O:\ eingebunden.
Jetzt können Hardlinks oder symbolische Verknüpfungen auf O:\ erstellt werden.
Bibliotheken für Entwickler:
Dokany – Ein Dateisystem-Treiber für Windows, der Cloud-Speicher als Laufwerk mountet.
rclone mount – Ein Tool, das beliebige Cloud-Speicher als Laufwerk einbindet.
Beispiel mit Dokany:
cpp
// Pseudocode (Dokany wird über eine DLL oder API gesteuert)
DokanMount(
L"O:\\", // Mount-Punkt
cloudProvider, // z. B. OneDrive, Google Drive
/* Optionen */
);
3. Cloud-Speicher als symbolische Verknüpfungen oder Junction Points einbinden
Einige Tools (z. B. Dropbox) nutzen symbolische Verknüpfungen, um Ordner in die lokale Struktur einzubinden.
Beispiel:
Dropbox erstellt einen Ordner C:\Users\Benutzer\Dropbox und bindet den Cloud-Speicher als Unterordner ein.
Technik:
Der Cloud-Ordner wird als symbolische Verknüpfung oder Junction Point in die lokale Struktur eingebunden.
C+±Beispiel für Junction Points:
cpp
#include <windows.h>
#include <iostream>
bool CreateJunction(LPCWSTR targetPath, LPCWSTR linkPath) {
if (CreateSymbolicLinkW(linkPath, targetPath, SYMBOLIC_LINK_FLAG_DIRECTORY | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)) {
std::wcout << L"Junction Point erfolgreich erstellt: " << linkPath << std::endl;
return true;
} else {
std::wcerr << L"Fehler beim Erstellen des Junction Points: " << GetLastError() << std::endl;
return false;
}
}
int main() {
CreateJunction(L"\\\\QNAP-NAS\\Qsync", L"C:\\Qsync");
return 0;
}
Hinweis: Junction Points funktionieren nur für Ordner, nicht für Dateien.
4. Spezielle Dateisystem-Treiber (z. B. für SMB, NFS, WebDAV)
Einige Tools nutzen spezielle Treiber, um Netzwerkprotokolle (SMB, NFS, WebDAV) direkt in das lokale Dateisystem zu integrieren.
Beispiel:
WebDrive oder ExpanDrive mounten FTP-, SFTP- oder WebDAV-Server als Laufwerke.
Technik: Ein Kernel-Treiber übersetzt die Netzwerkprotokolle in lokale Dateisystem-Operationen.
Zusammenfassung: Wie QNAP Qsync & Co. ferne Ordner einbinden
Methode Beispiel-Tools Funktioniert für Admin-Rechte nötig?
Netzlaufwerk mounten QNAP Qsync, Net use Netzwerkfreigaben (SMB) ✅ Ja
Cloud als Laufwerk OneDrive, Dropbox, Dokany Cloud-Speicher ✅ Ja (Treiber-Installation)
Symbolische Verknüpfungen Dropbox, Google Drive Ordner in lokaler Struktur ✅ Ja (für mklink)
Junction Points Mklink /J Ordner auf demselben Laufwerk ✅ Ja
Spezielle Treiber ExpanDrive, WebDrive FTP, SFTP, WebDAV ✅ Ja
Wie du das in deinem C+±Programm umsetzen kannst
Falls du ein Programm schreiben möchtest, das ferne Ordner wie lokale Laufwerke behandelt, könntest du:
Ein Netzlaufwerk mounten (mit WNetAddConnection2).
Einen symbolischen Verknüpfung oder Junction Point erstellen (mit CreateSymbolicLinkW).
Einen virtuellen Dateisystem-Treiber nutzen (z. B. Dokany).
Beispiel-Workflow:
mermaid
graph TD
A[Netzwerkfreigabe auswählen] --> B[Als Laufwerk mounten z. B. Q:\]
B --> C[Hardlink oder symbolische Verknüpfung erstellen]
C --> D[Fertig]
Next
Möchtest du ein komplettes C+±Beispiel, das Netzlaufwerke mountet und Hardlinks erstellt?
Brauchst du Hilfe bei der Integration von Dokany oder anderen Treibern?
Die Frage ist nicht wie Laufwerke aus fernen netzwerken eingebunden sind. Sondern nur einzelne Ordner 1:1 Beziehungen und Datei entweder als symlink (wenige bytes groß, cloud) oder physisch auf der HDD liegen nur gesteuert von der Nutzung.
Ah, jetzt verstehe ich die Kernfrage präziser! Du möchtest einzelne Ordner oder Dateien entweder als symbolische Verknüpfung (symlink, wenige Bytes groß, Cloud/Netzwerk) oder als physische Kopie auf der lokalen HDD vorhalten – und die Wahl soll dynamisch gesteuert werden, z. B. basierend auf der Nutzungshäufigkeit oder Verfügbarkeit.
Das ist ein häufiges Szenario für Tools wie:
Cloud-Sync-Clients (Dropbox, OneDrive, QNAP Qsync)
Offline-Verfügbarkeit (z. B. “Immer lokal verfügbar” vs. “Nur bei Bedarf”)
Speicheroptimierung (z. B. große Dateien nur als symlink, kleine Dateien physisch)
Wie funktioniert das technisch?
1. Symbolische Verknüpfungen (symlink)
Funktion: Zeigt auf einen Pfad (lokal oder remote), ohne die Daten zu kopieren.
Größe: Nur wenige Bytes (der Verknüpfungseintrag selbst).
Verfügbarkeit:
Cloud/Netzwerk: Funktioniert nur, wenn die Quelle verfügbar ist (z. B. Internetverbindung).
Lokal: Funktioniert immer, solange der Zielpfad existiert.
Einsatz:
Große Dateien, die selten genutzt werden.
Dateien, die in der Cloud/auf einem Server liegen.
2. Physische Kopie (Hardlink oder echte Kopie)
Funktion: Die Datei liegt physisch auf der lokalen HDD.
Größe: Vollständige Dateigröße.
Verfügbarkeit: Immer verfügbar, solange die Datei nicht gelöscht wird.
Einsatz:
Kleine Dateien, die häufig genutzt werden.
Dateien, die immer lokal verfügbar sein müssen.
Wie steuern Tools wie Qsync oder Dropbox die Auswahl?
Diese Tools nutzen eine Kombination aus:
Metadaten (z. B. letzte Nutzung, Dateigröße, Dateityp).
Benutzerdefinierte Regeln (z. B. “Immer lokal verfügbar”, “Nur bei Bedarf”).
Automatische Synchronisation (z. B. “Wenn offline, lade die Datei lokal herunter”).
Beispiel-Workflow (QNAP Qsync):
Neue Datei wird hinzugefügt:
Qsync prüft die Dateigröße und Nutzungshäufigkeit.
Kleine Dateien (z. B. < 1 MB) werden physisch lokal kopiert.
Große Dateien (z. B. > 100 MB) werden als symlink verknüpft.
Datei wird genutzt:
Wenn der Benutzer die Datei öffnet, prüft Qsync, ob sie lokal verfügbar ist.
Falls nicht, wird sie automatisch heruntergeladen (und ggf. als physische Kopie gespeichert).
Speicherplatz optimieren:
Selten genutzte Dateien werden automatisch gelöscht (nur der symlink bleibt).
Bei Bedarf wird die Datei neu heruntergeladen.
Wie kannst du das in C++ umsetzen?
Hier ein konzeptionelles Beispiel, wie du eine solche Logik in C++ implementieren könntest:
1. Datei- und Ordnerauswahl
cpp
#include <windows.h>
#include <iostream>
#include <filesystem>
#include <fstream>
#include <vector>
#include <map>
namespace fs = std::filesystem;
// Struktur für Datei-Informationen
struct FileInfo {
fs::path sourcePath; // Ursprungspfad (z. B. Cloud/Netzwerk)
fs::path localPath; // Lokale Verknüpfung oder Kopie
bool isSymbolicLink; // true = symlink, false = physische Kopie
time_t lastUsed; // Letzte Nutzung (für Automatisierung)
size_t fileSize; // Dateigröße (für Regeln)
};
// Regeln für die Auswahl (kannst du anpassen)
bool ShouldBeSymbolicLink(const FileInfo& file) {
// Beispielregeln:
// - Große Dateien (> 50 MB) als symlink
// - Kleine Dateien (< 1 MB) als physische Kopie
// - Dateien mit bestimmter Endung (z. B. .exe) immer lokal
if (file.fileSize > 50 * 1024 * 1024) { // > 50 MB
return true;
}
if (file.fileSize < 1 * 1024 * 1024) { // < 1 MB
return false;
}
return false; // Standard: physische Kopie
}
2. Symbolische Verknüpfung oder physische Kopie erstellen
cpp
// Symbolische Verknüpfung erstellen
bool CreateSymbolicLink(const fs::path& source, const fs::path& link) {
if (fs::exists(link)) {
fs::remove(link);
}
if (CreateSymbolicLinkW(link.c_str(), source.c_str(), 0)) {
std::wcout << L"Symbolische Verknüpfung erstellt: " << link << std::endl;
return true;
} else {
std::wcerr << L"Fehler beim Erstellen der symlink: " << GetLastError() << std::endl;
return false;
}
}
// Physische Kopie erstellen
bool CreatePhysicalCopy(const fs::path& source, const fs::path& target) {
try {
fs::copy_file(source, target, fs::copy_options::overwrite_existing);
std::wcout << L"Physische Kopie erstellt: " << target << std::endl;
return true;
} catch (const fs::filesystem_error& e) {
std::wcerr << L"Fehler beim Kopieren: " << e.what() << std::endl;
return false;
}
}
3. Datei “einbinden” (je nach Regel)
cpp
bool BindFile(const FileInfo& file) {
if (ShouldBeSymbolicLink(file)) {
return CreateSymbolicLink(file.sourcePath, file.localPath);
} else {
return CreatePhysicalCopy(file.sourcePath, file.localPath);
}
}
4. Automatische Synchronisation (Beispiel)
cpp
// Prüft, ob eine Datei lokal verfügbar ist, und lädt sie ggf. herunter
bool EnsureLocalAvailability(FileInfo& file) {
if (!fs::exists(file.localPath)) {
// Datei ist nicht lokal verfügbar -> herunterladen oder symlink erstellen
if (ShouldBeSymbolicLink(file)) {
return CreateSymbolicLink(file.sourcePath, file.localPath);
} else {
return CreatePhysicalCopy(file.sourcePath, file.localPath);
}
}
return true;
}
5. Beispiel: Alle Dateien in einem Ordner verarbeiten
cpp
void ProcessDirectory(const fs::path& sourceDir, const fs::path& localDir) {
for (const auto& entry : fs::directory_iterator(sourceDir)) {
if (entry.is_regular_file()) {
FileInfo file;
file.sourcePath = entry.path();
file.localPath = localDir / entry.path().filename();
file.fileSize = entry.file_size();
file.lastUsed = 0; // Hier könntest du die letzte Nutzung speichern
BindFile(file);
}
}
}
6. Beispielaufruf
cpp
int main() {
fs::path sourceDir = L"\\\\Server\\Freigabe\\Dokumente";
fs::path localDir = L"C:\\LokaleDokumente";
// Lokales Verzeichnis erstellen, falls nicht vorhanden
fs::create_directories(localDir);
// Dateien verarbeiten
ProcessDirectory(sourceDir, localDir);
return 0;
}
Erweiterungen für dein Szenario
1. Nutzungshäufigkeit tracken
Du kannst die letzte Nutzung einer Datei speichern (z. B. in einer Datenbank oder einer .ini-Datei) und basierend darauf entscheiden, ob die Datei als symlink oder physische Kopie vorgehalten wird.
Beispiel:
Wenn eine Datei länger als 30 Tage nicht genutzt wurde, wird sie als symlink gespeichert.
Wenn sie häufig genutzt wird, wird sie als physische Kopie vorgehalten.
2. Automatische Umwandlung
Du kannst eine Logik implementieren, die automatisch zwischen symlink und physischer Kopie umwandelt, z. B.:
Bei Speichermangel werden selten genutzte Dateien zu symlinks.
Bei häufiger Nutzung werden symlinks zu physischen Kopien.
Beispiel:
cpp
void OptimizeStorage(const fs::path& localDir) {
for (const auto& entry : fs::directory_iterator(localDir)) {
if (entry.is_regular_file()) {
FileInfo file;
file.localPath = entry.path();
file.fileSize = entry.file_size();
file.lastUsed = GetLastFileUsage(file.localPath); // Aus Datenbank lesen
// Regel: Wenn Datei selten genutzt wird, zu symlink umwandeln
if (file.lastUsed < time(nullptr) - 30 * 24 * 60 * 60) { // 30 Tage nicht genutzt
fs::remove(file.localPath);
file.sourcePath = GetSourcePath(file.localPath); // Ursprungspfad aus Datenbank
CreateSymbolicLink(file.sourcePath, file.localPath);
}
}
}
}
3. Cloud/Netzwerk-Verfügbarkeit prüfen
Bevor du einen symlink erstellst, solltest du prüfen, ob die Quelle verfügbar ist (z. B. Internetverbindung oder Netzlaufwerk erreichbar).
Beispiel:
cpp
bool IsSourceAvailable(const fs::path& sourcePath) {
// Für Netzwerkpfade: Prüfen, ob das Laufwerk verfügbar ist
if (sourcePath.string().find(L"\\\\") == 0) {
DWORD driveType = GetDriveType(sourcePath.string().substr(0, 2).c_str());
return (driveType == DRIVE_REMOTE);
}
// Für Cloud/Internet: Ping oder API-Aufruf
return true; // Vereinfacht
}
4. Benutzerdefinierte Regeln
Du kannst benutzerdefinierte Regeln implementieren, z. B.:
“Immer lokal verfügbar”: Bestimmte Dateitypen (z. B. .exe, .docx) werden immer als physische Kopie gespeichert.
“Nur bei Bedarf”: Große Mediendateien (z. B. .mp4, .iso) werden nur als symlink vorgehalten.
Beispiel:
cpp
bool ShouldAlwaysBeLocal(const fs::path& filePath) {
std::vector<std::wstring> localExtensions = {L".exe", L".docx", L".pdf"};
std::wstring ext = filePath.extension().wstring();
for (const auto& e : localExtensions) {
if (ext == e) {
return true;
}
}
return false;
}
Zusammenfassung: Wie du das umsetzen kannst
Schritt Methode Tools/APIs
Datei auswählen Pfad der Datei (lokal/remote) std::filesystem
Regel prüfen Dateigröße, Nutzungshäufigkeit, Typ Benutzerdefinierte Logik
Symbolische Verknüpfung erstellen CreateSymbolicLinkW Windows-API
Physische Kopie erstellen fs::copy_file C++17 Filesystem
Verfügbarkeit prüfen Netzwerk/Cloud-Verbindung GetDriveType, Ping, API-Aufrufe
Automatische Umwandlung Nutzungshäufigkeit tracken Datenbank oder .ini-Datei
Next
Möchtest du ein komplettes C+±Projekt, das diese Logik implementiert?
Brauchst du Hilfe bei der Integration in ein bestehendes Tool (z. B. Qsync-Alternative)?
Soll ich dir zeigen, wie du Nutzungshäufigkeit in einer SQLite-Datenbank speicherst?
ein komplettes C+±Projekt, das diese Logik implementiert. Gibt es Libs und Projekte z.B. auf github die das implementieren?
Hier ist ein komplettes C+±Projekt, das die Logik für dynamische Verknüpfungen (symlink vs. physische Kopie) basierend auf Dateigröße, Nutzungshäufigkeit und benutzerdefinierten Regeln implementiert.
Das Projekt enthält:
✅ Kernlogik für die Auswahl zwischen symlink und physischer Kopie
✅ Nutzungshäufigkeit tracken (in einer SQLite-Datenbank)
✅ Automatische Umwandlung (z. B. bei Speichermangel oder Nutzung)
✅ Fehlerbehandlung und Logging
✅ Beispiel-Code für Windows (mit CreateSymbolicLinkW und std::filesystem)
1. Projektstruktur
DynamicFileBinder/
│── CMakeLists.txt # CMake-Konfiguration
│── src/
│ ├── main.cpp # Hauptprogramm
│ ├── FileBinder.cpp # Kernlogik
│ ├── FileBinder.h # Header
│ ├── Database.cpp # SQLite-Integration
│ ├── Database.h # Header
│ └── Logger.cpp # Logging
│── include/
│ └── FileBinder.h # Öffentliche Header
│── data/
│ └── usage.db # SQLite-Datenbank für Nutzungshäufigkeit
│── tests/ # Beispiel-Tests
└── README.md
2. Kerncode: FileBinder (Kernlogik)
FileBinder.h
cpp
#pragma once
#include <filesystem>
#include <string>
#include <vector>
#include <ctime>
namespace fs = std::filesystem;
struct FileInfo {
fs::path sourcePath; // Ursprungspfad (z. B. Cloud/Netzwerk)
fs::path localPath; // Lokale Verknüpfung oder Kopie
bool isSymbolicLink; // true = symlink, false = physische Kopie
time_t lastUsed; // Letzte Nutzung (Unix-Timestamp)
size_t fileSize; // Dateigröße in Bytes
std::string fileType; // Dateityp (z. B. ".txt", ".mp4")
};
class FileBinder {
public:
FileBinder(const fs::path& localBaseDir);
// Datei einbinden (symlink oder physische Kopie)
bool BindFile(const FileInfo& fileInfo);
// Datei "nutzen" (lastUsed aktualisieren)
bool MarkFileAsUsed(const fs::path& localPath);
// Automatische Optimierung: Selten genutzte Dateien zu symlinks umwandeln
void OptimizeStorage(size_t maxLocalStorageMB);
// Benutzerdefinierte Regeln für die Auswahl
static bool ShouldBeSymbolicLink(const FileInfo& file);
private:
fs::path localBaseDir_;
size_t GetDirectorySizeMB(const fs::path& dir);
};
FileBinder.cpp
cpp
#include "FileBinder.h"
#include "Database.h"
#include "Logger.h"
#include <windows.h>
#include <fstream>
#include <sstream>
#include <filesystem>
namespace fs = std::filesystem;
FileBinder::FileBinder(const fs::path& localBaseDir) : localBaseDir_(localBaseDir) {
fs::create_directories(localBaseDir_);
}
bool FileBinder::BindFile(const FileInfo& fileInfo) {
fs::path targetPath = localBaseDir_ / fileInfo.localPath.filename();
// Falls die Datei bereits existiert, löschen
if (fs::exists(targetPath)) {
fs::remove(targetPath);
}
// Regel prüfen: Soll die Datei als symlink oder physische Kopie gespeichert werden?
if (ShouldBeSymbolicLink(fileInfo)) {
if (CreateSymbolicLinkW(
targetPath.c_str(),
fileInfo.sourcePath.c_str(),
0)) {
LogInfo("Erstellt symlink: " + targetPath.string());
return true;
} else {
LogError("Fehler beim Erstellen des symlinks: " + std::to_string(GetLastError()));
return false;
}
} else {
try {
fs::copy_file(fileInfo.sourcePath, targetPath, fs::copy_options::overwrite_existing);
LogInfo("Erstellt physische Kopie: " + targetPath.string());
return true;
} catch (const fs::filesystem_error& e) {
LogError("Fehler beim Kopieren: " + std::string(e.what()));
return false;
}
}
}
bool FileBinder::MarkFileAsUsed(const fs::path& localPath) {
try {
Database db("data/usage.db");
fs::path fullPath = localBaseDir_ / localPath;
time_t now = time(nullptr);
return db.UpdateFileUsage(fullPath.string(), now);
} catch (const std::exception& e) {
LogError("Fehler beim Markieren als genutzt: " + std::string(e.what()));
return false;
}
}
void FileBinder::OptimizeStorage(size_t maxLocalStorageMB) {
Database db("data/usage.db");
auto files = db.GetFilesOlderThan(30); // Dateien, die älter als 30 Tage sind
size_t currentSizeMB = GetDirectorySizeMB(localBaseDir_);
for (const auto& file : files) {
if (currentSizeMB >= maxLocalStorageMB) {
fs::path localPath = localBaseDir_ / fs::path(file.path).filename();
if (fs::exists(localPath)) {
fs::remove(localPath);
FileInfo info;
info.sourcePath = file.path; // In der Praxis müsstest du den Ursprungspfad hier speichern
info.localPath = localPath;
info.isSymbolicLink = true;
info.fileSize = file.size;
info.lastUsed = file.lastUsed;
info.fileType = file.type;
BindFile(info);
currentSizeMB = GetDirectorySizeMB(localBaseDir_);
}
}
}
}