Problém s oprávněním složky   otázka

VB.NET, I/O operace, Bezpečnost

Dobrý den,

Mohl by mi někdo poradit kde dělam chybu v tomto kódu.

    Dim slozky As Collections.ObjectModel.ReadOnlyCollection(Of String)
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Try
            slozky = Microsoft.VisualBasic.FileIO.FileSystem.GetDirectories("c:\", FileIO.SearchOption.SearchAllSubDirectories)
        Catch ex As UnauthorizedAccessException
        End Try
        For i = 0 To slozky.Count - 1
            TextBox1.Text &= slozky(i) & Environment.NewLine
        Next
    End Sub
nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zajímalo by mě jak jste k tomuto paskvilu dospěl.

ReadOnlyCollection je kolekce pouze pro čtení a lze ji naplnit pouze v konstruktoru. Máte ji navíc definovanou jako String, GetDirectories ovšem vrací pole typu DirectoryInfo.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Nevím sice, kde na to kolega přišel, ale po stylistické stránce je to kupodivu dobře.

Metoda GetDirectories je v různých jmenných prostorech definována různě a i ta v příkladu uvedená definice tam je.

A kupodivu to dokonce funguje (nevím sice, co znamená "ReadOnlyCollection", přesněji jaký má význam, ale postupem uvedeným v příkladu se do ní dá docela pohodlně zapisovat.

Problém je jinde. Pokud si totiž jako výchozí dáte adresář, pod kterým nejsou žádné adresáře do kterých byste neměl přístup, vše funguje (i přesně v provedení, jaké napsal tazatel).

Příkaz GetDirectories si ale neporadí s uzlem, do kterého Vás systém vzhledem k přístupovým právům nepustí, nebo jsem alespoň nenašel k tomuto cestu - už kdysi mooc dávno jsem to (i tady) řešil a nakonec jsem celý problém musel řešit rekurzí, kde jsem si přístupová práva ohlídal sám.

Pročež bych se zeptal zkušenějších:

1) je možno toto omezení metody getdirectories nějak obejít?

2) k čemu teda je readOnlyCollection, když není ReadOnly? (že by to znamenalo to, že do této kolekce je možno pouze prvotně přiřadit, ale nemá, jak jsem zjistil, metody typu "Add"?

nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět

Omezení s přístupovými oprávněními se skutečně dají řešit pouze rekurzivní funkcí.

ReadOnlyCollection(Of T) je speciální druh kolekce, která je pouze pro čtení. Tedy nelze ji přímo modifikovat (přidávat, odstraňovat, nebo měnit její obsah).

Naplníte ji tak, že předáte libovolný IList(Of T) v jejím konstruktoru, ten se uvnitř drží jako reference a tedy veškeré změny provedené v této v konstruktoru předané kolekci se projeví i v dané ReadOnlyCollection.

ReadOnlyCollection se používá tam, kde je nežádoucí měnit obsah kolekce, například při předávání parametrů v EventArgs nějaké události.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Moc tomu zatím nerozumím, ale chtěl bych to změnit. Nepokročil jsem moc daleko a nevím jestli je to správně.

 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim sl As IList(Of String)
        sl = Microsoft.VisualBasic.FileIO.FileSystem.GetDirectories("d:\", FileIO.SearchOption.SearchAllSubDirectories)


    End Sub

Tady jsem se zasekl a nevím jak dál.

Prosím poraďte.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Už to tu máte napsané - procházet složky. Tak můžete nepřístupné složky přeskočit.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Jestli myslíte toto

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim sl As IList(Of String)
        Try
        Catch ex As UnauthorizedAccessException
            sl = Microsoft.VisualBasic.FileIO.FileSystem.GetDirectories("c:\", FileIO.SearchOption.SearchAllSubDirectories)
        End Try


       End Sub

tak při konečném zapisovaní dojde opět k chybě. Nevím jak má vypadat ten konstruktor.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Procházením je myšleno číst složky jednu po druhé (v opakovacím cyklu) a rekurzí opakování kódu - procedura volá sama sebe (pro čtení vnořené složky):

  Sub VypisSlozky(ByVal dir As String)
    Dim startDir As New IO.DirectoryInfo(dir)
    Try
      For Each directory As IO.DirectoryInfo In startDir.GetDirectories()
        TextBox1.Text &=  directory.FullName & Environment.NewLine
        VypisSlozky(directory.FullName)
      Next

    Catch ex As UnauthorizedAccessException
      'Chyba oprávnění k procházení složkou
      TextBox1.Text &= "*** " & ex.Message & Environment.NewLine
    End Try
  End Sub

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Nějak to nefungovalo, možná jsem to dělal špatně. Když sem to změnil tak to fungovalo. Za Sub sem napsal New a odmazal VypisSlozky(directory.FullName)

teď to funguje, už jen dodělám výpis i podsložek a bude to.

Zatím nevím jak.

    Sub New(ByVal dir As String)
        Dim startDir As New IO.DirectoryInfo(dir)
        Try
            For Each directory As IO.DirectoryInfo In startDir.GetDirectories()
                Form1.TextBox1.Text &= directory.FullName & Environment.NewLine
            Next

        Catch ex As UnauthorizedAccessException
            'Chyba oprávnění k procházení složkou
            Form1.TextBox1.Text &= "*** " & ex.Message & Environment.NewLine
        End Try
    End Sub

Děkuji za pomoc.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Použít rekurzi:

Function VypisSlozky(dir As String) As List(Of String)
    Dim slozky As List(Of String)   'seznam složek
    PridejSlozky(dir, slozky)       'přidá složky do seznamu
    Return slozky
End Function

Sub PridejSlozky(dir As String, slozky As List(Of String))
    'přidat složky z aktuálního adresáře a z jeho podadresářů do seznamu
    Try
        For Each d As String In IO.Directory.GetDirectories(dir)
            'přidat podsložku d do seznamu složek
            slozky.Add(d)

            'zkusit tam přidat všechny složky z této podsložky d
            PridejSlozky(d, slozky)    
        Next

    Catch UnauthorizedAccessException
        'pokud nejsou práva, kašleme na to
    End Try

End Sub

Tomu, že metodu PridejSlozky voláte zevnitř sebe samotné, se říká rekurze, máme tady o ní na webu také nějaké články. Stačí si uvědomit, že metoda PridejSlozky přidá do seznamu, který jí předáte v parametru slozky, všechny složky ve složce dir a v jejích podsložkách.

Celou tu opičárnu zavoláte tou první metodou, která si vytvoří seznam přidá si do něj všechny složky a vrátí ho.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Děkuji za pomoc.

Jen myslím,že správné znění 18. řádku má být

Catch ex As UnauthorizedAccessException

jen nepodstatná chybka.

ješte mám problém s přidáním výpisu do texboxu

TextBox1.Text = VypisSlozky("c:\" ???)

nevím jak to má pokračovat.

Ješte jednou děkuji.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Pokud se koukneš pořádně na Tomášův kód jistě rychle zjistíš, že jeho funkce VypisSlozky vrací seznam složek (v List kolekci). Proto ten výsledek nelze přiřadit přímo do textboxu.

A ani by to nebylo ideální, protože výsledek je v LIST-u seřazen tak, jak ho vytvořil ten rekurzivní algoritmus, což není vždy přesně to, co by od toho člověk očekával.

Proto bych doporučil vrácený list si nejprve seřadit a pak jej teprve vypsat (položku po položce) do textboxu.

Nepředpokládám, že by tento způsob výpisu podadresářů byl použitelný pro něco rozsáhlejšího, ale upozorňuji, že pokud se pokusíš vypsat tímto způsobem třeba to obligátní "c:\", pak se pěkně načekáš (těch podadresářů bývají tisíce), a získáš stejně nepoužitelný mnohatisíciřádkový textbox (trochu se ten výpis dá urychlit třeba tím, že si ten obsah nejprve poskládáš do textbuilderu, ale i tak bych to pro praxi moc použitelné neviděl)

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback